From bef6322859a5dc01e35d884de7afd2eabb1d9e4d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 17 May 2007 22:22:53 +0000 Subject: at basic locking/threading support git-svn-id: file:///home/lennart/svn/public/libsydney/trunk@26 9ba3c220-e4d3-45a2-8aa3-73fcc9aff6ce --- once.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 once.c (limited to 'once.c') diff --git a/once.c b/once.c new file mode 100644 index 0000000..de41be3 --- /dev/null +++ b/once.c @@ -0,0 +1,58 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "once.h" +#include "mutex.h" +#include "malloc.h" +#include "macro.h" + +static sa_mutex_t *global_mutex; +static pthread_once_t global_mutex_once = PTHREAD_ONCE_INIT; + +static void global_mutex_once_func(void) { + global_mutex = sa_mutex_new(0); +} + +int sa_once(sa_once_t *control, sa_once_func_t func) { + int r; + + assert(control); + assert(func); + + /* Create the global mutex */ + sa_assert_success(pthread_once(&global_mutex_once, global_mutex_once_func)); + + if (!global_mutex) + return -1; + + r = 0; + + /* Create the local mutex */ + sa_mutex_lock(global_mutex); + if (!control->mutex) { + if (!(control->mutex = sa_mutex_new(1))) + r = -1; + } + sa_mutex_unlock(global_mutex); + + if (!r) + return -1; + + /* Execute function */ + sa_mutex_lock(control->mutex); + if (!control->once_value) { + control->once_value = 1; + func(); + } + sa_mutex_unlock(control->mutex); + + /* Caveat: We have to make sure that the once func has completed + * before returning, even if the once func is not actually + * executed by us. Hence the awkward locking. */ + + return 0; +} -- cgit