Lifetimes and Threads
Destroying objects
Every object holds a libxkbcommon object, which the garbage collector does
not free. Destroy each object when you are done with it, either with its
with- macro or its destroy- function:
| Object | Make | Destroy | Scoped |
|---|---|---|---|
context |
make-context |
destroy-context |
with-context |
keymap |
make-keymap, make-keymap-from-string |
destroy-keymap |
with-keymap |
keyboard-state |
make-keyboard-state |
destroy-keyboard-state |
with-keyboard-state |
compose-table |
make-compose-table, make-compose-table-from-string |
destroy-compose-table |
with-compose-table |
compose-state |
make-compose-state |
destroy-compose-state |
with-compose-state |
The with- macros destroy the object when the body exits, whether normally
or by a non-local exit. with-keymap and with-compose-table take the same
arguments as make-keymap and make-compose-table. To scope a keymap made
from text, use make-keymap-from-string with unwind-protect and
destroy-keymap.
What outlives what
An object keeps the libxkbcommon objects it was made from alive. So objects can be destroyed in any order:
- A keymap and a compose table stay usable after their context is destroyed.
- A keyboard state stays usable after its keymap is destroyed, modifiers included.
- A compose state stays usable after its compose table is destroyed.
(let* ((context (xkb:make-context))
(keymap (xkb:make-keymap context :layout "us"))
(state (xkb:make-keyboard-state keymap)))
(xkb:destroy-context context)
(xkb:destroy-keymap keymap)
(xkb:update-key state 50 :press)
(list (xkb:key-text state 38) (xkb:active-modifiers state))) ; => ("A" (:SHIFT))
The libxkbcommon objects are freed once nothing uses them.
Using a destroyed object
An object that has been destroyed signals an xkb-error when used,
including when destroyed a second time. It prints as (destroyed):
(xkb:destroy-keyboard-state state)
state ; => #<XKB:KEYBOARD-STATE (destroyed) {...}>
(xkb:key-text state 38) ; signals XKB-ERROR: ... has been destroyed and cannot be used.
The one exception is take-log-messages. It still returns what a destroyed
context logged before it was destroyed.
Threads
| Object | Rule |
|---|---|
keymap |
may be read from several threads at once |
context |
belongs to one thread at a time |
keyboard-state |
belongs to one thread at a time |
compose-table |
belongs to one thread at a time |
compose-state |
belongs to one thread at a time |
"Belongs to one thread at a time" means that an object may move between threads, for example from a loading thread to the main thread, but two threads must not use it at once without a lock.
Keymaps can be shared because nothing changes a keymap after it is compiled. Several threads can make their own keyboard states from one keymap and use them in parallel.
The functions that take no object, find-keysym, keysym-name,
keysym-character, character-keysym and evdev-keycode, may be called
from any thread.
Allocation
A keymap looks up its modifiers once, when it is made. After that, these allocate nothing:
key-keysymmodifier-active-pandmodifier-consumed-p, whether the modifier is a keyword or a stringupdate-keyandupdate-modifierswhen nothing changed
active-modifiers and key-shortcut return a fresh list of modifiers, but
no list at all when there are none. key-text, key-press-text, compose-text and
keysym-name return fresh strings, since they return text.