]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/once.h
merge 'lennart' branch back into trunk.
[pulseaudio] / src / pulsecore / once.h
index a82a3c86064f0bf6826300e5bbcf576c6fc54ffd..c9fe6d0a4942a726384de853bd4c7ce9ac53118d 100644 (file)
@@ -5,38 +5,72 @@
 
 /***
   This file is part of PulseAudio.
+
+  Copyright 2006 Lennart Poettering
+
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.
+
   PulseAudio is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   General Public License for more details.
+
   You should have received a copy of the GNU Lesser General Public
   License along with PulseAudio; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
   USA.
 ***/
 
+#include <pulsecore/mutex.h>
 #include <pulsecore/atomic.h>
 
 typedef struct pa_once {
-    pa_atomic_int_t atomic;
-} pa_once_t;
+    pa_atomic_ptr_t mutex;
+    pa_atomic_t ref, done;
+} pa_once;
 
-#define PA_ONCE_INIT { PA_ATOMIC_INIT(0) }
+#define PA_ONCE_INIT                                                    \
+    {                                                                   \
+        .mutex = PA_ATOMIC_PTR_INIT(NULL),                              \
+        .ref = PA_ATOMIC_INIT(0),                                       \
+        .done = PA_ATOMIC_INIT(0)                                       \
+    }
 
-#define pa_once_test(o) (pa_atomic_cmpxchg(&(o)->atomic, 0, 1))
+/* Not to be called directly, use the macros defined below instead */
+int pa_once_begin(pa_once *o);
+void pa_once_end(pa_once *o);
 
-typedef void (*pa_once_func_t) (void);
+#define PA_ONCE_BEGIN                                                   \
+    do {                                                                \
+        static pa_once _once = PA_ONCE_INIT;                            \
+        if (pa_once_begin(&_once)) {{
+
+#define PA_ONCE_END                                                     \
+            }                                                           \
+            pa_once_end(&_once);                                        \
+        }                                                               \
+    } while(0)
+
+/*
 
-static inline void pa_once(pa_once_t *o, pa_once_func_t f) {
-    if (pa_once_test(o))
-        f();
-}
+  Usage of these macros is like this:
+
+  void foo() {
+
+      PA_ONCE_BEGIN {
+
+          ... stuff to be called just once ...
+
+      } PA_ONCE_END;
+  }
+
+*/
+
+/* Same API but calls a function */
+typedef void (*pa_once_func_t) (void);
+void pa_run_once(pa_once *o, pa_once_func_t f);
 
 #endif