diff options
Diffstat (limited to '')
-rw-r--r-- | src/libmdsclient/proto-util.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/libmdsclient/proto-util.c b/src/libmdsclient/proto-util.c index f104d05..85b755f 100644 --- a/src/libmdsclient/proto-util.c +++ b/src/libmdsclient/proto-util.c @@ -743,3 +743,49 @@ int libmds_compose_v(char** restrict buffer, size_t* restrict buffer_size, size_ return 0; } + +/** + * Increase the message ID counter + * + * @param message_id Pointer to the current message ID, will be update with + * the next free message ID. Must not be `NULL`. + * @param test Function that tests whether an message ID is free, + * it takes the message ID to test as its first argument, + * and `data` as its second argument, and returns zero if + * it is in used, a positive integer if it is free, and a + * negative integer if an error occurred. `NULL` if there + * should be no testing. + * @param data Argument to pass to `test` so that it can deal with + * threading or any other issues. Unused if `test` is `NULL`. + * @return Zero on success, -1 on error, `errno` will have been set + * accordingly on error. + * + * @throws EAGAIN If there are no free message ID to be used. + * It is advisable to make `test` throw this immediately if + * there are no free message ID:s. + * @throws Any error that `test` may throw. + */ +int libmds_next_message_id(uint32_t* restrict message_id, + int (*test)(uint32_t message_id, void* data), void* data) +{ + uint32_t id = *message_id; + int r; + + id = id == UINT32_MAX ? 0 : (id + 1); + if (test != NULL) + for (;;) + { + r = test(id, data); + if (r < 0) + return -1; + if (r) + break; + id = id == UINT32_MAX ? 0 : (id + 1); + if (id == *message_id) + return errno = EAGAIN, -1; + } + + *message_id = id; + return 0; +} + |