6 Lifetimes and Threads
dxtr edited this page 2026-10-17 04:51:55 +02:00

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-keysym
  • modifier-active-p and modifier-consumed-p, whether the modifier is a keyword or a string
  • update-key and update-modifiers when 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.