Registry

Header: libxs_reg.h

Thread-safe key-value store backed by a hash table with per-thread caching.

Configuration Macros

Macro Default Description
LIBXS_REGKEY_MAXSIZE 64 Maximum key size in bytes
LIBXS_REGISTRY_NBUCKETS 64 Initial hash-table buckets (power of two); registries grow dynamically
LIBXS_REGCACHE_NENTRIES 16 Thread-local cache entries per thread (power of two; 0 disables caching)

Types

typedef struct libxs_registry_t libxs_registry_t;   /* opaque */
typedef struct libxs_registry_info_t {
  size_t capacity, size, nbytes;
} libxs_registry_info_t;

Lifetime

libxs_registry_t* libxs_registry_create(void);

Create a new registry. Returns NULL in case of an error.

void libxs_registry_destroy(libxs_registry_t* registry);

Destroy a registry and release all entries.

libxs_lock_t* libxs_registry_lock(libxs_registry_t* registry);

Return a pointer to the registry's internal lock. The returned lock can be passed as the lock argument to other registry functions (e.g., to hold the lock across multiple operations).

Iteration

void* libxs_registry_begin(libxs_registry_t* registry,
  const void** key, size_t* cursor);
void* libxs_registry_next(libxs_registry_t* registry,
  const void** key, size_t* cursor);

Enumerate entries. Initialize *cursor to 0 before the first begin call. Each call returns the value pointer and writes the key pointer to *key, or returns NULL when iteration is complete.

Access

void* libxs_registry_set(libxs_registry_t* registry,
  const void* key, size_t key_size,
  const void* value_init, size_t value_size,
  libxs_lock_t* lock /* = NULL */);

Insert or update a key-value pair. The key must be binary-reproducible (zero-initialize padding). value_init may be NULL to defer initialization. Re-registering an existing key reallocates if the new value is larger. When lock is NULL the registry's internal lock is used. Returns a pointer to the stored value.

void* libxs_registry_get(const libxs_registry_t* registry,
  const void* key, size_t key_size,
  libxs_lock_t* lock /* = NULL */);

Look up a value by key. Returns NULL if not found.

int libxs_registry_get_copy(const libxs_registry_t* registry,
  const void* key, size_t key_size,
  void* value_out, size_t value_size,
  libxs_lock_t* lock /* = NULL */);

Thread-safe query: copies up to value_size bytes of the stored value into value_out under the lock. Unlike libxs_registry_get, the caller never receives a raw pointer into the registry's internal storage, making this safe under concurrent modifications. Returns non-zero if the key was found, zero otherwise.

int libxs_registry_has(libxs_registry_t* registry,
  const void* key, size_t key_size,
  libxs_lock_t* lock /* = NULL */);

Check whether a key exists. Non-zero if found.

size_t libxs_registry_value_size(libxs_registry_t* registry,
  const void* key, size_t key_size,
  libxs_lock_t* lock /* = NULL */);

Query the stored value size in bytes. Returns 0 if not found.

void libxs_registry_remove(libxs_registry_t* registry,
  const void* key, size_t key_size,
  libxs_lock_t* lock /* = NULL */);

Remove a key-value pair and release its memory.

int libxs_registry_extract(libxs_registry_t* registry,
  const void* key, size_t key_size,
  void* value_out, size_t value_size,
  libxs_lock_t* lock /* = NULL */);

Atomically retrieve and remove a key-value pair. Copies up to value_size bytes of the stored value into value_out (may be NULL to discard the value), then removes the entry and releases its memory. The lookup, copy, and removal are performed under a single lock hold, eliminating the race that exists when calling libxs_registry_get followed by libxs_registry_remove separately. Returns non-zero if the key was found, zero otherwise.

Status

int libxs_registry_info(libxs_registry_t* registry,
  libxs_registry_info_t* info);

Query registry capacity, number of entries, and total bytes stored.