From bd53e7ee4c45e7cef357f8aba2e8cb842ac11e92 Mon Sep 17 00:00:00 2001 From: Russell Bryant Date: Thu, 19 Oct 2006 01:00:57 +0000 Subject: Extend the thread storage API such that a custom initialization function can be called for each thread specific object after they are allocated. Note that there was already the ability to define a custom cleanup function. Also, if the custom cleanup function is used, it *MUST* call free on the thread specific object at the end. There is no way to have this magically done that I can think of because the cleanup function registered with the pthread implementation will only call the function back with a pointer to the thread specific object, not the parent ast_threadstorage object. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@45623 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- include/asterisk/threadstorage.h | 54 +++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 17 deletions(-) (limited to 'include/asterisk') diff --git a/include/asterisk/threadstorage.h b/include/asterisk/threadstorage.h index 14c6d65b9..6964839cb 100644 --- a/include/asterisk/threadstorage.h +++ b/include/asterisk/threadstorage.h @@ -41,35 +41,51 @@ struct ast_threadstorage { pthread_key_t key; /*! The function that initializes the key */ void (*key_init)(void); + /*! Custom initialization function specific to the object */ + void (*custom_init)(void *); }; /*! * \brief Define a thread storage variable * - * \arg name The name of the thread storage - * \arg name_init This is a name used to create the function that gets called - * to initialize this thread storage. It can be anything since it will not - * be referred to anywhere else + * \arg name The name of the thread storage object * * This macro would be used to declare an instance of thread storage in a file. * * Example usage: * \code - * AST_THREADSTORAGE(my_buf, my_buf_init); + * AST_THREADSTORAGE(my_buf); + * \endcode + */ +#define AST_THREADSTORAGE(name) \ + AST_THREADSTORAGE_CUSTOM(name, NULL, NULL) + +/*! + * \brief Define a thread storage variable, with custom initialization and cleanup + * + * \arg name The name of the thread storage object + * \arg init This is a custom that will be called after each thread specific + * object is allocated, with the allocated block of memory passed + * as the argument. + * \arg cleanup This is a custom function that will be called instead of ast_free + * when the thread goes away. Note that if this is used, it *MUST* + * call free on the allocated memory. + * + * Example usage: + * \code + * AST_THREADSTORAGE(my_buf, my_init, my_cleanup); * \endcode */ -#define AST_THREADSTORAGE(name, name_init) \ - AST_THREADSTORAGE_CUSTOM(name, name_init, ast_free) - -#define AST_THREADSTORAGE_CUSTOM(name, name_init, cleanup) \ -static void name_init(void); \ -static struct ast_threadstorage name = { \ - .once = PTHREAD_ONCE_INIT, \ - .key_init = name_init, \ -}; \ -static void name_init(void) \ -{ \ - pthread_key_create(&(name).key, cleanup); \ +#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); \ } /*! @@ -111,6 +127,8 @@ void *ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size), if (!(buf = pthread_getspecific(ts->key))) { if (!(buf = ast_calloc(1, init_size))) return NULL; + if (ts->custom_init) + ts->custom_init(buf); pthread_setspecific(ts->key, buf); } @@ -118,6 +136,8 @@ void *ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size), } ) +void __ast_threadstorage_cleanup(void *); + /*! * \brief A dynamic length string */ -- cgit v1.2.3