ID Map

Internally, NNG uses a map of numeric identifiers to data structures. This feature is also exposed for application use, as a “supplemental” feature.

When using these functions, it is necessary to add the #include <nng/supplemental/util/idhash.h> include file to list of includes.

ID Map Structure

#include <nng/nng.h>
#include <nng/supplemental/util/idhash.h>

typedef struct nng_id_map_s nng_id_map;

The ID map structure, nng_id_map provides a table of identifiers mapping to user-supplied pointers (which must not be NULL). The identifiers can be thought of as indices into the table, with the pointers providing the reference for the user supplied data.

The values of identifiers can be supplied by the user, or can be allocated automatically by nng_id_map from a predefined range. The starting point for allocations can also be randomly within the range.

The identifiers are 64-bit unsigned integers and can be sparse; the structure will use space efficiently even if identifiers are very far apart. 1

important

The function available for nng_id_map are not thread-safe. Callers should use a mutex or similar approach when thread-safety is needed.

Create ID Map

#define NNG_MAP_RANDOM 1

int nng_id_map_alloc(nng_id_map **map_p, uint64_t lo, uint64_t hi, int flags);

The nng_id_map_alloc function allocates a map without any data in it, and returns a pointer to it in map_p. When allocating identifiers dynamically, the values will be chosen from the range defined by lo and hi, inclusive.

The flags argument is a bit mask of flags that can adjust behavior of the map. The only flag defined at present is NNG_MAP_RANDOM, which causes the first identifier allocation to start at a random point within the range. This is useful to reduce the odds of different instances of an application using the same identifiers at the same time.

If both lo and hi are zero, then the values 0 and 0xffffffff are substituted in their place, giving a full range of 32-bit identifiers.

This function can return NNG_ENOMEM if it is unable to allocate resources, otherwise it returns zero on success.

Destroy Map

void nng_id_map_free(nng_id_map *map);

The nng_id_map_free function destroys map, releasing any resources associated with it.

note

The nng_id_map_free frees the map itself, but will not free memory associated with any strctures contained within it.

Store a Value

int nng_id_set(nng_id_map *map, uint64_t id, void *value);

The nng_id_map_set function is used to store the value in the map at index id.

If another value is already stored at that same location, then it is overwritten with value.

note

The value must not be NULL.

If the table has to grow to accommodate this value, it may fail if insufficient memory is available, returning NNG_ENOMEM. Otherwise it returns zero.

Lookup a Value

void *nng_id_get(nng_id_map *map, uint64_t id);

The nng_id_get function looks up the entry for id in map, returning the associated value if present, or NULL if no such entry exists.

Allocate an ID

int nng_id_alloc(nng_id_map *map, uint64_t *id_p, void *value);

The nng_id_alloc stores the value in the map, at a newly allocated index, and returns the index in id_p.

Identifiers are allocated in increasing order, without reusing old identifiers until the largest possible identifier is allocated. After wrapping, only identifiers that are no longer in use will be considered. No effort is made to order the availability of identifiers based on when they were freed.2

As with nng_id_set, this may need to allocate memory and can thus fail with NNG_ENOMEM.

Additionally, if there are no more free identifiers within the range specified when map was created, then it will return NNG_ENOSPC.

Otherwise it returns zero, indicating success.

Remove an ID

int nng_id_remove(nng_id_map *map, uint64_t id);

The nng_id_remove removes the entry at index id from map.

If no such entry exist, it will return NNG_ENOENT. Otherwise it returns zero.

Iterating IDs

bool nng_id_visit(nng_id_map *map, uint64_t *id_p, void **value_p, uint32_t *cursor);

The nng_id_visit function is used to iterate over all items in the table. The caller starts the iteration by setting the cursor to 0 before calling it. For each call, the associated key and value of the next item will be returned in id_p, and value_p and the cursor will be updated. When all items have been iterated, the function returns false. The order of items returned is not guaranteed to be sequential. The caller must not attempt to derive any value of the cursor as it refers to internal table indices.

Entries may be safely removed from map while iterating.

However, if new entries are added to the table while iterating, the result of iteration is undefined; entries may be repeated or omitted during such an iteration.

The caller must not attempt to derive any value of the cursor as it refers to internal table indices.


1: The ID map is capable of storing at most 232 identifiers, even though the identifers may themselves be much larger than this.

2: The concern about possibly reusing a recently released identifier comes into consideration after the range has wrapped. Given a sufficiently large range, this is unlikely to be a concern.