58#pragma clang diagnostic push
59#pragma clang diagnostic ignored "-Wunused-macros"
60#pragma clang diagnostic ignored "-Wreserved-id-macro"
61#pragma clang diagnostic ignored "-Wclass-varargs"
62#pragma clang diagnostic ignored "-Wbuiltin-requires-header"
63#pragma clang diagnostic ignored "-W#warnings"
70#define _POSIX_SOURCE 200112L
77#ifndef _DARWIN_C_SOURCE
78#define _DARWIN_C_SOURCE 200112L
79#define __DARWIN_C_LEVEL 200112L
91#define __block _xblock
94#define __block __attribute__((__blocks__(byref)))
95#pragma clang diagnostic pop
100#include <sys/param.h>
108#ifdef BUILD_WB_LIBRARY_GUWHITEBOARD
114#define WHITEBOARD_MAGIC 0xfeeda11deadbeef5ULL
115#define SEMAPHORE_MAGIC_KEY 4242
124#ifdef _SEM_SEMUN_UNDEFINED
128 struct semid_ds *buf;
129 unsigned short int *array;
130 struct seminfo *__buf;
143 if (s[i]) dispatch_release(s[i]);
144 s[i] = dispatch_semaphore_create(init.val);
146#pragma clang diagnostic push
147#pragma clang diagnostic ignored "-Wclass-varargs"
148 if (semctl(s, i, SETVAL, init) == -1)
149 fprintf(stderr,
"Warning; failed to initialise whiteboard semaphore %d: %s\n", i, strerror(errno));
151 if (semctl(s, i, GETVAL, NULL) != init.val)
152 fprintf(stderr,
"Warning; failed to initialise whiteboard semaphore %d: %s\n", i, strerror(errno));
154#pragma clang diagnostic pop
187 fprintf(stderr,
"Warning: whiteboard '%s' tries to define %d messages, but only %d reserved\n", name, nmsgs,
GSW_NUM_TYPES_DEFINED);
193 if (wbd == NULL)
return NULL;
198 snprintf(type_str,
sizeof(type_str),
"not a type: %d", nmsgs++);
211 fprintf(stderr,
"Not enough memory to create whiteboard '%s': %s\n", name, strerror(errno));
217 fprintf(stderr,
"Warning; cannot get semaphore %d for whiteboard '%s': %s (proceeding without)\n", semaphore_magic_key, name, strerror(errno));
219 bool needs_init =
false;
230 for (
int i = 0; i < num_messages; i++)
233#ifdef WITHOUT_LIBDISPATCH
260#ifndef WITHOUT_LIBDISPATCH
267static void create_singleton_whiteboard(
void *context)
273#ifndef GSW_IOS_DEVICE
275 if (env && *env) name = env;
283#ifdef WITHOUT_LIBDISPATCH
287 create_singleton_whiteboard(NULL);
290 static dispatch_once_t onceToken;
291 dispatch_once_f(&onceToken, NULL, create_singleton_whiteboard);
305 if (!name || strlen(name) > PATH_MAX-strlen(path)-1) name =
GSW_DEFAULT_NAME;
306 gu_strlcat(path, name,
sizeof(path));
308 int fd = open(path, O_CREAT|O_RDWR, 0666);
311 fprintf(stderr,
"Cannot open/create '%s': %s\n", path, strerror(errno));
316 fprintf(stderr,
"Warning; cannot reserve %lu bytes for '%s': %s\n", (
unsigned long)
sizeof(
gu_simple_whiteboard), path, strerror(errno));
318 gu_simple_whiteboard *wb = mmap(NULL,
sizeof(*wb), PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fd, 0);
321 fprintf(stderr,
"Cannot mmap '%s': %s\n", path, strerror(errno));
325 else if (fdp) *fdp = fd;
329 memset(wb, 0,
sizeof(*wb));
333 if (initial) *initial =
true;
335 DBG(printf(
"New Whiteboard version %d created and initialised at '%s'\n", wb->
version, path));
337 else if (initial) *initial =
false;
353 if (munmap(wb,
sizeof(*wb)) == -1)
354 fprintf(stderr,
"Cannot unmap whiteboard at %p with fd %d: %s\n", (
void *)wb, fd, strerror(errno));
355 if (fd >= 0)
if (close(fd) == -1)
356 fprintf(stderr,
"Cannot close whiteboard at %p with fd %d: %s\n", (
void *)wb, fd, strerror(errno));
363 while (dispatch_semaphore_wait(sem[s], DISPATCH_TIME_FOREVER))
370 struct sembuf op = { (
unsigned short) s, -1, 0 };
372 while ((rv = semop(sem, &op, 1)) == -1)
383 dispatch_semaphore_signal(sem[s]);
386 struct sembuf op = { (
unsigned short) s, 1, 0 };
388 while ((rv = semop(sem, &op, 1)) == -1)
447 DBG(printf(
" - registering wb message type #%d for '%s' at %d\n", wb->
num_types, type->
hash.
string, offs));
458 DBG(printf(
"Hash collision at offset %u: %u == %u %% %d for:\n'%s' <> '%s'",
461 offs += alt_hash(name);
470 fprintf(stderr,
"Cannot register whiteboard message type '%s': hash table capacity %d reached!\n", name, wb->
num_types);
489 offs += alt_hash(name);
493 fprintf(stderr,
"Cannot get offset for message type '%s': hash table full (%d entries)\n", name, wb->
num_types);
526#pragma mark - subscription and callbacks
542 else fprintf(stderr,
"Warning: process table full (%d): cannot subscribe %d\n", i, proc);
561 else fprintf(stderr,
"Warning: cannot remove %d -- process not found!\n", proc);
568#ifdef USE_WHITEBOARD_SIGNAL
577#ifndef WITHOUT_LIBDISPATCH
578static void subscription_callback(
void *param)
584static void monitor_subscriptions(
void *param)
595 dispatch_async_f(wbd->
callback_queue, wbd, subscription_callback);
607static void sig_handler(
int signum)
616 if (old_handler == SIG_DFL)
619#ifndef WITHOUT_LIBDISPATCH
623 dispatch_async_f(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), wbd, monitor_subscriptions);
gu_simple_whiteboard_descriptor * local_whiteboard_descriptor
gu_simple_message * gsw_next_message(gu_simple_whiteboard *wb, int i)
get the next shared memory location for the given whiteboard message type i
void gsw_add_wbd_signal_handler(gu_simple_whiteboard_descriptor *wbd)
add subscription signal handler
void gsw_free_whiteboard(gu_simple_whiteboard_descriptor *wbd)
free the given whiteboard descriptor
void gsw_free(gu_simple_whiteboard *wb, int fd)
free the whiteboard
gsw_sema_t gsw_setup_semaphores(int key)
set up a semaphore array for the whiteboard
void gsw_increment(gu_simple_whiteboard *wb, int i)
get the next shared memory location for the given whiteboard message type i
void gsw_increment_event_counter(gu_simple_whiteboard *wb, int i)
add to a messages event counter on the wb
gu_simple_whiteboard_descriptor * gsw_new_custom_whiteboard(const char *name, const char *message_names[], int num_messages, int semaphore_magic_key)
Access a named, custom whiteboard.
void(* gsw_sig_t)(int sig)
gu_simple_whiteboard_descriptor * get_local_singleton_whiteboard(void)
create a simple whiteboard for the local singleton wb pointer
gu_simple_whiteboard_descriptor * gsw_new_whiteboard(const char *name)
access a named whiteboard: this is the designated constructore for C programs
gu_simple_message * gsw_current_message(gu_simple_whiteboard *wb, int i)
get the current shared memory location for the given whiteboard message type i
int gsw_procure(gsw_sema_t sem, enum gsw_semaphores s)
grab a whiteboard semaphore
int gsw_offset_for_message_type(gu_simple_whiteboard_descriptor *wbd, const char *name)
get the numerical index of a whiteboard message type
void gsw_init_semaphores(gsw_sema_t s)
initialise the whiteboard semaphores
int gsw_register_message_type(gu_simple_whiteboard_descriptor *wbd, const char *name)
register a new whiteboard message type
gu_simple_whiteboard_descriptor * gsw_new_numbered_whiteboard(const char *name, int n)
access a named whiteboard: this is the designated standard wb constructor for C programs that want to...
void gsw_remove_wbd_signal_handler(gu_simple_whiteboard_descriptor *wbd)
remove subscription signal handler
gu_simple_whiteboard * gsw_create(const char *name, int *fdp, bool *initial)
create a simple whiteboard
void gsw_remove_process(gu_simple_whiteboard_descriptor *wbd, const pid_t proc)
remove process for subscription signalling
int gsw_vacate(gsw_sema_t sem, enum gsw_semaphores s)
release a whiteboard semaphore
void gsw_add_process(gu_simple_whiteboard_descriptor *wbd, const pid_t proc)
add process for subscription signalling
#define SEMAPHORE_MAGIC_KEY
gu_simple_whiteboard_descriptor * gswr_new_whiteboard(int i)
access a remote named whiteboard: this is the designated constructore for C programs
void gsw_signal_subscribers(gu_simple_whiteboard *wb)
signal all subscribing processes
#define GSW_DEFAULT_NAME
fallback default wb
#define GU_SIMPLE_WHITEBOARD_GENERATIONS
lifespan (max)
#define GU_SIMPLE_WHITEBOARD_VERSION
version
#define GSW_TOTAL_PROCESSES
maximum subscriber procs
const char ** WBTypes_stringValues
allow whiteboard to use old functions for whiteboard initialisation and choose which messages and con...
#define GSW_NUM_TYPES_DEFINED
allow whiteboard to use old functions for whiteboard initialisation and choose which messages and con...
#define GSW_DEFAULT_ENV
environment variable containing the default whiteboard file name
#define WHITEBOARD_SIGNAL
#define GSW_TOTAL_MESSAGE_TYPES
message types (max)
#define WHITEBOARD_POLL_PERIOD
@ GSW_NUM_SEM
number of semaphores
@ GSW_SEM_MSGTYPE
semaphore for message type registration
@ GSW_SEM_PROC
semaphore for process registration
#define GSWR_BASE_NAME
UDP whiteboard name.
#define GU_SIMPLE_WHITEBOARD_BUFSIZE
message len (max)
the actual whiteboard in shared mem
uint16_t version
whiteboard version
uint16_t eventcount
current event count
gu_simple_message typenames[512]
message types for numbers
pid_t processes[256]
list of subscribed processes
uint8_t indexes[512]
ring buffer indexes
gu_simple_message hashes[512]
hashes for registered message types
uint16_t num_types
total number of current, registered types
uint64_t magic
end of whiteboard marker
uint16_t event_counters[512]
event counter loops
gu_simple_message messages[512][4]
the actual messages stored in the whiteboard
uint16_t subscribed
subscribed processes
the underlying whiteboard object
bool got_monitor
have a running monitor
bool exit_monitor
exit the monitor
gsw_subscription_f callback
subscription callback function
dispatch_queue_t callback_queue
subscription callback queue
int fd
the associated memory-mapped file
gsw_sema_t sem
semaphore to use
gu_simple_whiteboard * wb
the actual whiteboard in shared mem
union type that is used to store data in shared memory
char string[128]
string type
struct gsw_simple_message::@3 hash
whiteboard hash type