aboutsummaryrefslogtreecommitdiffstats
path: root/src/libmdsclient/proto-util.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2015-08-25 02:31:37 +0200
committerMattias Andrée <maandree@operamail.com>2015-08-25 02:32:02 +0200
commitef73e4a7a5748c7685a61eae34ccb5de991f86a7 (patch)
tree4b7363f989fb7d71b3e0af20d21c442001ffeced /src/libmdsclient/proto-util.c
parentlibmdsclient: add identity macros for optimisation functions that may or may not disappear in the future, and may or may not get alternatives, this... (diff)
downloadmds-ef73e4a7a5748c7685a61eae34ccb5de991f86a7.tar.gz
mds-ef73e4a7a5748c7685a61eae34ccb5de991f86a7.tar.bz2
mds-ef73e4a7a5748c7685a61eae34ccb5de991f86a7.tar.xz
libmdsclient: add function to find unused message id
Signed-off-by: Mattias Andrée <maandree@operamail.com>
Diffstat (limited to 'src/libmdsclient/proto-util.c')
-rw-r--r--src/libmdsclient/proto-util.c46
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;
+}
+