aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/bus.c154
-rw-r--r--src/bus.h107
2 files changed, 220 insertions, 41 deletions
diff --git a/src/bus.c b/src/bus.c
index 6705854..06c708a 100644
--- a/src/bus.c
+++ b/src/bus.c
@@ -33,6 +33,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <time.h>
#include <sys/ipc.h>
#include <sys/sem.h>
@@ -422,6 +423,36 @@ mkdirs(char *pathname, mode_t mode)
}
+/**
+ * Convert an absolute time to a relative time
+ *
+ * @param delta Output parameter for the relative time
+ * @param absolute The absolute time
+ * @param clockid The ID of the clock the time is measured in
+ * @return 0 on success, -1 on error
+ */
+static int
+absolute_time_to_delta_time(struct timespec *delta, const struct timespec *absolute, clockid_t clockid)
+{
+ if (clock_gettime(clockid, delta) < 0)
+ return -1;
+
+ delta->tv_sec = absolute->tv_sec - delta->tv_sec;
+ delta->tv_nsec = absolute->tv_nsec - delta->tv_nsec;
+
+ if (delta->tv_nsec < 0L) {
+ delta->tv_nsec += 1000000000L;
+ delta->tv_sec -= 1;
+ }
+ if (delta->tv_nsec >= 1000000000L) {
+ delta->tv_nsec -= 1000000000L;
+ delta->tv_sec += 1;
+ }
+
+ return 0;
+}
+
+
/**
* Create a new bus
@@ -632,7 +663,7 @@ fail:
/**
- * Broadcast a message a bus
+ * Broadcast a message on a bus
*
* @param bus Bus information
* @param message The message to write, may not be longer than
@@ -677,26 +708,49 @@ fail:
/**
+ * Broadcast a message on a bus
+ *
+ * @param bus Bus information
+ * @param message The message to write, may not be longer than
+ * `BUS_MEMORY_SIZE` including the NUL-termination
+ * @param timeout The time the operation shall fail with errno set
+ * to `EAGAIN` if not completed
+ * @param clockid The ID of the clock the `timeout` is measured with,
+ * it most be a predictable clock
+ * @return 0 on success, -1 on error
+ */
+int bus_write_timed(const bus_t *bus, const char *message,
+ const struct timespec *timeout, clockid_t clockid)
+{
+ /* TODO bus_write_timed */
+ if (!timeout)
+ return bus_write(bus, message, 0);
+ (void) bus, (void) message, (void) timeout, (void) clockid;
+}
+
+
+/**
* Listen (in a loop, forever) for new message on a bus
*
- * @param bus Bus information
- * @param callback Function to call when a message is received, the
- * input parameters will be the read message and
- * `user_data` from `bus_read`'s parameter with the
- * same name. The message must have been parsed or
- * copied when `callback` returns as it may be over
- * overridden after that time. `callback` should
- * return either of the the values:
- * * 0: stop listening
- * * 1: continue listening
- * * -1: an error has occurred
- * However, the function [`bus_read`] will invoke
- * `callback` with `message` set to `NULL`one time
- * directly after it has started listening on the
- * bus. This is to the the program now it can safely
- * continue with any action that requires that the
- * programs is listening on the bus.
- * @return 0 on success, -1 on error
+ * @param bus Bus information
+ * @param callback Function to call when a message is received, the
+ * input parameters will be the read message and
+ * `user_data` from `bus_read`'s parameter with the
+ * same name. The message must have been parsed or
+ * copied when `callback` returns as it may be over
+ * overridden after that time. `callback` should
+ * return either of the the values:
+ * * 0: stop listening
+ * * 1: continue listening
+ * * -1: an error has occurred
+ * However, the function [`bus_read`] will invoke
+ * `callback` with `message` set to `NULL`one time
+ * directly after it has started listening on the
+ * bus. This is to the the program now it can safely
+ * continue with any action that requires that the
+ * programs is listening on the bus.
+ * @param user_data Parameter passed to `callback`
+ * @return 0 on success, -1 on error
*/
int
bus_read(const bus_t *bus, int (*callback)(const char *message, void *user_data), void *user_data)
@@ -738,6 +792,44 @@ done:
/**
+ * Listen (in a loop, forever) for new message on a bus
+ *
+ * @param bus Bus information
+ * @param callback Function to call when a message is received, the
+ * input parameters will be the read message and
+ * `user_data` from `bus_read`'s parameter with the
+ * same name. The message must have been parsed or
+ * copied when `callback` returns as it may be over
+ * overridden after that time. `callback` should
+ * return either of the the values:
+ * * 0: stop listening
+ * * 1: continue listening
+ * * -1: an error has occurred
+ * However, the function [`bus_read`] will invoke
+ * `callback` with `message` set to `NULL`one time
+ * directly after it has started listening on the
+ * bus. This is to the the program now it can safely
+ * continue with any action that requires that the
+ * programs is listening on the bus.
+ * @param user_data Parameter passed to `callback`
+ * @param timeout The time the operation shall fail with errno set
+ * to `EAGAIN` if not completed, note that the callback
+ * function may or may not have been called
+ * @param clockid The ID of the clock the `timeout` is measured with,
+ * it most be a predictable clock
+ * @return 0 on success, -1 on error
+ */
+int bus_read_timed(const bus_t *bus, int (*callback)(const char *message, void *user_data),
+ void *user_data, const struct timespec *timeout, clockid_t clockid)
+{
+ /* TODO bus_read_timed */
+ if (!timeout)
+ return bus_read(bus, callback, user_data);
+ (void) bus, (void) callback, (void) user_data, (void) timeout, (void) clockid;
+}
+
+
+/**
* Announce that the thread is listening on the bus.
* This is required so the will does not miss any
* messages due to race conditions. Additionally,
@@ -835,6 +927,30 @@ fail:
/**
+ * Wait for a message to be broadcasted on the bus.
+ * The caller should make a copy of the received message,
+ * without freeing the original copy, and parse it in a
+ * separate thread. When the new thread has started be
+ * started, the caller of this function should then
+ * either call `bus_poll_timed` again or `bus_poll_stop`.
+ *
+ * @param bus Bus information
+ * @param timeout The time the operation shall fail with errno set
+ * to `EAGAIN` if not completed
+ * @param clockid The ID of the clock the `timeout` is measured with,
+ * it most be a predictable clock
+ * @return The received message, `NULL` on error
+ */
+const char *bus_poll_timed(bus_t *bus, const struct timespec *timeout, clockid_t clockid)
+{
+ /* TODO bus_poll_timed */
+ if (!timeout)
+ return bus_poll(bus);
+ (void) bus, (void) timeout, (void) clockid;
+}
+
+
+/**
* Change the ownership of a bus
*
* `stat(2)` can be used of the bus's associated file to get the bus's ownership
diff --git a/src/bus.h b/src/bus.h
index 8c73677..aa35c7b 100644
--- a/src/bus.h
+++ b/src/bus.h
@@ -29,6 +29,7 @@
# define _DEFAULT_SOURCE
#endif
#include <sys/types.h>
+#include <time.h>
@@ -158,7 +159,7 @@ int bus_close(bus_t *bus);
/**
- * Broadcast a message a bus
+ * Broadcast a message on a bus
*
* @param bus Bus information
* @param message The message to write, may not be longer than
@@ -169,32 +170,78 @@ int bus_close(bus_t *bus);
* @return 0 on success, -1 on error
*/
int bus_write(const bus_t *bus, const char *message, int flags);
-/* TODO bus_write_timed */
+
+/**
+ * Broadcast a message on a bus
+ *
+ * @param bus Bus information
+ * @param message The message to write, may not be longer than
+ * `BUS_MEMORY_SIZE` including the NUL-termination
+ * @param timeout The time the operation shall fail with errno set
+ * to `EAGAIN` if not completed
+ * @param clockid The ID of the clock the `timeout` is measured with,
+ * it most be a predictable clock
+ * @return 0 on success, -1 on error
+ */
+int bus_write_timed(const bus_t *bus, const char *message,
+ const struct timespec *timeout, clockid_t clockid);
+
/**
* Listen (in a loop, forever) for new message on a bus
*
- * @param bus Bus information
- * @param callback Function to call when a message is received, the
- * input parameters will be the read message and
- * `user_data` from `bus_read`'s parameter with the
- * same name. The message must have been parsed or
- * copied when `callback` returns as it may be over
- * overridden after that time. `callback` should
- * return either of the the values:
- * * 0: stop listening
- * * 1: continue listening
- * * -1: an error has occurred
- * However, the function [`bus_read`] will invoke
- * `callback` with `message` set to `NULL`one time
- * directly after it has started listening on the
- * bus. This is to the the program now it can safely
- * continue with any action that requires that the
- * programs is listening on the bus.
- * @return 0 on success, -1 on error
+ * @param bus Bus information
+ * @param callback Function to call when a message is received, the
+ * input parameters will be the read message and
+ * `user_data` from `bus_read`'s parameter with the
+ * same name. The message must have been parsed or
+ * copied when `callback` returns as it may be over
+ * overridden after that time. `callback` should
+ * return either of the the values:
+ * * 0: stop listening
+ * * 1: continue listening
+ * * -1: an error has occurred
+ * However, the function [`bus_read`] will invoke
+ * `callback` with `message` set to `NULL`one time
+ * directly after it has started listening on the
+ * bus. This is to the the program now it can safely
+ * continue with any action that requires that the
+ * programs is listening on the bus.
+ * @param user_data Parameter passed to `callback`
+ * @return 0 on success, -1 on error
*/
int bus_read(const bus_t *bus, int (*callback)(const char *message, void *user_data), void *user_data);
-/* TODO bus_read_timed */
+
+/**
+ * Listen (in a loop, forever) for new message on a bus
+ *
+ * @param bus Bus information
+ * @param callback Function to call when a message is received, the
+ * input parameters will be the read message and
+ * `user_data` from `bus_read`'s parameter with the
+ * same name. The message must have been parsed or
+ * copied when `callback` returns as it may be over
+ * overridden after that time. `callback` should
+ * return either of the the values:
+ * * 0: stop listening
+ * * 1: continue listening
+ * * -1: an error has occurred
+ * However, the function [`bus_read`] will invoke
+ * `callback` with `message` set to `NULL`one time
+ * directly after it has started listening on the
+ * bus. This is to the the program now it can safely
+ * continue with any action that requires that the
+ * programs is listening on the bus.
+ * @param user_data Parameter passed to `callback`
+ * @param timeout The time the operation shall fail with errno set
+ * to `EAGAIN` if not completed, note that the callback
+ * function may or may not have been called
+ * @param clockid The ID of the clock the `timeout` is measured with,
+ * it most be a predictable clock
+ * @return 0 on success, -1 on error
+ */
+int bus_read_timed(const bus_t *bus, int (*callback)(const char *message, void *user_data),
+ void *user_data, const struct timespec *timeout, clockid_t clockid);
/**
@@ -235,7 +282,23 @@ int bus_poll_stop(const bus_t *bus);
* @return The received message, `NULL` on error
*/
const char *bus_poll(bus_t *bus);
-/* TODO bus_poll_timed */
+
+/**
+ * Wait for a message to be broadcasted on the bus.
+ * The caller should make a copy of the received message,
+ * without freeing the original copy, and parse it in a
+ * separate thread. When the new thread has started be
+ * started, the caller of this function should then
+ * either call `bus_poll_timed` again or `bus_poll_stop`.
+ *
+ * @param bus Bus information
+ * @param timeout The time the operation shall fail with errno set
+ * to `EAGAIN` if not completed
+ * @param clockid The ID of the clock the `timeout` is measured with,
+ * it most be a predictable clock
+ * @return The received message, `NULL` on error
+ */
+const char *bus_poll_timed(bus_t *bus, const struct timespec *timeout, clockid_t clockid);
/**