]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/thread.h
Create a new macro for checking compiler support for TLS.
[pulseaudio] / src / pulsecore / thread.h
index ca1fe4da84f4373ee82add93f94eba830c45093e..87e850d67eae41221c92c595c6655fd70d1695ad 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef foopulsethreadhfoo
 #define foopulsethreadhfoo
 
-/* $Id$ */
-
 /***
   This file is part of PulseAudio.
 
 ***/
 
 #include <pulse/def.h>
+#include <pulsecore/once.h>
+
+#ifndef PACKAGE
+#error "Please include config.h before including this file!"
+#endif
 
 typedef struct pa_thread pa_thread;
 
@@ -48,4 +51,60 @@ void pa_tls_free(pa_tls *t);
 void * pa_tls_get(pa_tls *t);
 void *pa_tls_set(pa_tls *t, void *userdata);
 
+#define PA_STATIC_TLS_DECLARE(name, free_cb)                            \
+    static struct {                                                     \
+        pa_once once;                                                   \
+        pa_tls *tls;                                                    \
+    } name##_tls = {                                                    \
+        .once = PA_ONCE_INIT,                                           \
+        .tls = NULL                                                     \
+    };                                                                  \
+    static void name##_tls_init(void) {                                 \
+        name##_tls.tls = pa_tls_new(free_cb);                           \
+    }                                                                   \
+    static inline pa_tls* name##_tls_obj(void) {                        \
+        pa_run_once(&name##_tls.once, name##_tls_init);                 \
+        return name##_tls.tls;                                          \
+    }                                                                   \
+    static void name##_tls_destructor(void) PA_GCC_DESTRUCTOR;          \
+    static void name##_tls_destructor(void) {                           \
+        static void (*_free_cb)(void*) = free_cb;                       \
+        if (!name##_tls.tls)                                            \
+            return;                                                     \
+        if (_free_cb) {                                                 \
+            void *p;                                                    \
+            if ((p = pa_tls_get(name##_tls.tls)))                       \
+                _free_cb(p);                                            \
+        }                                                               \
+        pa_tls_free(name##_tls.tls);                                    \
+    }                                                                   \
+    static inline void* name##_tls_get(void) {                          \
+        return pa_tls_get(name##_tls_obj());                            \
+    }                                                                   \
+    static inline void* name##_tls_set(void *p) {                       \
+        return pa_tls_set(name##_tls_obj(), p);                         \
+    }                                                                   \
+    struct __stupid_useless_struct_to_allow_trailing_semicolon
+
+#ifdef SUPPORT_TLS___THREAD
+/* An optimized version of the above that requires no dynamic
+ * allocation if the compiler supports __thread */
+#define PA_STATIC_TLS_DECLARE_NO_FREE(name)                             \
+    static __thread void *name##_tls = NULL;                            \
+    static inline void* name##_tls_get(void) {                          \
+        return name##_tls;                                              \
+    }                                                                   \
+    static inline void* name##_tls_set(void *p) {                       \
+        void *r = name##_tls;                                           \
+        name##_tls = p;                                                 \
+        return r;                                                       \
+    }                                                                   \
+    struct __stupid_useless_struct_to_allow_trailing_semicolon
+#else
+#define PA_STATIC_TLS_DECLARE_NO_FREE(name) PA_STATIC_TLS_DECLARE(name, NULL)
+#endif
+
+#define PA_STATIC_TLS_GET(name) (name##_tls_get())
+#define PA_STATIC_TLS_SET(name, p) (name##_tls_set(p))
+
 #endif