yeah... so... compiling before committing seems like it might be a good idea
[asterisk/asterisk.git] / include / asterisk / threadstorage.h
index 469f463..1fd0f04 100644 (file)
@@ -62,6 +62,12 @@ struct ast_threadstorage {
        int (*custom_init)(void *); /*!< Custom initialization function specific to the object */
 };
 
+#if defined(DEBUG_THREADLOCALS)
+void __ast_threadstorage_object_add(void *key, size_t len, const char *file, const char *function, unsigned int line);
+void __ast_threadstorage_object_remove(void *key);
+void __ast_threadstorage_object_replace(void *key_old, void *key_new, size_t len);
+#endif /* defined(DEBUG_THREADLOCALS) */
+
 /*!
  * \brief Define a thread storage variable
  *
@@ -93,17 +99,36 @@ struct ast_threadstorage {
  * AST_THREADSTORAGE_CUSTOM(my_buf, my_init, my_cleanup);
  * \endcode
  */
-#define AST_THREADSTORAGE_CUSTOM(name, c_init, c_cleanup) \
-static void init_##name(void);                            \
-static struct ast_threadstorage name = {                  \
-       .once = PTHREAD_ONCE_INIT,                        \
-       .key_init = init_##name,                          \
-       .custom_init = c_init,                            \
-};                                                        \
-static void init_##name(void)                             \
-{                                                         \
-       pthread_key_create(&(name).key, c_cleanup);       \
+#if !defined(DEBUG_THREADLOCALS)
+#define AST_THREADSTORAGE_CUSTOM(name, c_init, c_cleanup)      \
+static void __init_##name(void);                               \
+static struct ast_threadstorage name = {                       \
+       .once = PTHREAD_ONCE_INIT,                              \
+       .key_init = __init_##name,                              \
+       .custom_init = c_init,                                  \
+};                                                             \
+static void __init_##name(void)                                        \
+{                                                              \
+       pthread_key_create(&(name).key, c_cleanup);             \
+}
+#else /* defined(DEBUG_THREADLOCALS) */
+#define AST_THREADSTORAGE_CUSTOM(name, c_init, c_cleanup)      \
+static void __init_##name(void);                               \
+static struct ast_threadstorage name = {                       \
+       .once = PTHREAD_ONCE_INIT,                              \
+       .key_init = __init_##name,                              \
+       .custom_init = c_init,                                  \
+};                                                             \
+static void __cleanup_##name(void *data)                       \
+{                                                              \
+       __ast_threadstorage_object_remove(data);                \
+       c_cleanup(data);                                        \
+}                                                              \
+static void __init_##name(void)                                        \
+{                                                              \
+       pthread_key_create(&(name).key, __cleanup_##name);      \
 }
+#endif /* defined(DEBUG_THREADLOCALS) */
 
 /*!
  * \brief Retrieve thread storage
@@ -135,6 +160,7 @@ static void init_##name(void)                             \
  * }
  * \endcode
  */
+#if !defined(DEBUG_THREADLOCALS)
 AST_INLINE_API(
 void *ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size),
 {
@@ -154,7 +180,29 @@ void *ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size),
        return buf;
 }
 )
+#else /* defined(DEBUG_THREADLOCALS) */
+AST_INLINE_API(
+void *__ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size, const char *file, const char *function, unsigned int line),
+{
+       void *buf;
+
+       pthread_once(&ts->once, ts->key_init);
+       if (!(buf = pthread_getspecific(ts->key))) {
+               if (!(buf = ast_calloc(1, init_size)))
+                       return NULL;
+               if (ts->custom_init && ts->custom_init(buf)) {
+                       free(buf);
+                       return NULL;
+               }
+               pthread_setspecific(ts->key, buf);
+               __ast_threadstorage_object_add(buf, init_size, file, function, line);
+       }
+
+       return buf;
+}
+)
 
-void __ast_threadstorage_cleanup(void *);
+#define ast_threadstorage_get(ts, init_size) __ast_threadstorage_get(ts, init_size, __FILE__, __PRETTY_FUNCTION__, __LINE__)
+#endif /* defined(DEBUG_THREADLOCALS) */
 
 #endif /* ASTERISK_THREADSTORAGE_H */