00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 2006, Digium, Inc. 00005 * 00006 * Russell Bryant <russell@digium.com> 00007 * 00008 * See http://www.asterisk.org for more information about 00009 * the Asterisk project. Please do not directly contact 00010 * any of the maintainers of this project for assistance; 00011 * the project provides a web site, mailing lists and IRC 00012 * channels for your use. 00013 * 00014 * This program is free software, distributed under the terms of 00015 * the GNU General Public License Version 2. See the LICENSE file 00016 * at the top of the source tree. 00017 */ 00018 00019 /*! 00020 * \file threadstorage.h 00021 * \author Russell Bryant <russell@digium.com> 00022 * 00023 * \brief Definitions to aid in the use of thread local storage 00024 */ 00025 00026 #ifndef ASTERISK_THREADSTORAGE_H 00027 #define ASTERISK_THREADSTORAGE_H 00028 00029 #include <pthread.h> 00030 00031 #include "asterisk/utils.h" 00032 #include "asterisk/inline_api.h" 00033 00034 /*! 00035 * \brief data for a thread locally stored variable 00036 */ 00037 struct ast_threadstorage { 00038 /*! Ensure that the key is only initialized by one thread */ 00039 pthread_once_t once; 00040 /*! The key used to retrieve this thread's data */ 00041 pthread_key_t key; 00042 /*! The function that initializes the key */ 00043 void (*key_init)(void); 00044 }; 00045 00046 #if defined(DEBUG_THREADLOCALS) 00047 void __ast_threadstorage_object_add(void *key, size_t len, const char *file, const char *function, unsigned int line); 00048 void __ast_threadstorage_object_remove(void *key); 00049 void __ast_threadstorage_object_replace(void *key_old, void *key_new, size_t len); 00050 #endif /* defined(DEBUG_THREADLOCALS) */ 00051 00052 /*! 00053 * \brief Define a thread storage variable 00054 * 00055 * \arg name The name of the thread storage 00056 * \arg name_init This is a name used to create the function that gets called 00057 * to initialize this thread storage. It can be anything since it will not 00058 * be referred to anywhere else 00059 * 00060 * This macro would be used to declare an instance of thread storage in a file. 00061 * 00062 * Example usage: 00063 * \code 00064 * AST_THREADSTORAGE(my_buf, my_buf_init); 00065 * \endcode 00066 */ 00067 #define AST_THREADSTORAGE(name, name_init) \ 00068 AST_THREADSTORAGE_CUSTOM(name, name_init, ast_free_ptr) 00069 00070 #if defined(PTHREAD_ONCE_INIT_NEEDS_BRACES) 00071 # define AST_PTHREAD_ONCE_INIT { PTHREAD_ONCE_INIT } 00072 #else 00073 # define AST_PTHREAD_ONCE_INIT PTHREAD_ONCE_INIT 00074 #endif 00075 00076 #if !defined(DEBUG_THREADLOCALS) 00077 #define AST_THREADSTORAGE_CUSTOM(name, name_init, cleanup) \ 00078 static void name_init(void); \ 00079 static struct ast_threadstorage name = { \ 00080 .once = AST_PTHREAD_ONCE_INIT, \ 00081 .key_init = name_init, \ 00082 }; \ 00083 static void name_init(void) \ 00084 { \ 00085 pthread_key_create(&(name).key, cleanup); \ 00086 } 00087 #else /* defined(DEBUG_THREADLOCALS) */ 00088 #define AST_THREADSTORAGE_CUSTOM(name, name_init, cleanup) \ 00089 static void name_init(void); \ 00090 static struct ast_threadstorage name = { \ 00091 .once = AST_PTHREAD_ONCE_INIT, \ 00092 .key_init = name_init, \ 00093 }; \ 00094 static void __cleanup_##name(void *data) \ 00095 { \ 00096 __ast_threadstorage_object_remove(data); \ 00097 cleanup(data); \ 00098 } \ 00099 static void name_init(void) \ 00100 { \ 00101 pthread_key_create(&(name).key, __cleanup_##name); \ 00102 } 00103 #endif /* defined(DEBUG_THREADLOCALS) */ 00104 00105 /*! 00106 * \brief Retrieve thread storage 00107 * 00108 * \arg ts This is a pointer to the thread storage structure declared by using 00109 * the AST_THREADSTORAGE macro. If declared with 00110 * AST_THREADSTORAGE(my_buf, my_buf_init), then this argument would be 00111 * (&my_buf). 00112 * \arg init_size This is the amount of space to be allocated the first time 00113 * this thread requests its data. Thus, this should be the size that the 00114 * code accessing this thread storage is assuming the size to be. 00115 * 00116 * \return This function will return the thread local storage associated with 00117 * the thread storage management variable passed as the first argument. 00118 * The result will be NULL in the case of a memory allocation error. 00119 * 00120 * Example usage: 00121 * \code 00122 * AST_THREADSTORAGE(my_buf, my_buf_init); 00123 * #define MY_BUF_SIZE 128 00124 * ... 00125 * void my_func(const char *fmt, ...) 00126 * { 00127 * void *buf; 00128 * 00129 * if (!(buf = ast_threadstorage_get(&my_buf, MY_BUF_SIZE))) 00130 * return; 00131 * ... 00132 * } 00133 * \endcode 00134 */ 00135 #if !defined(DEBUG_THREADLOCALS) 00136 AST_INLINE_API( 00137 void *ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size), 00138 { 00139 void *buf; 00140 00141 pthread_once(&ts->once, ts->key_init); 00142 if (!(buf = pthread_getspecific(ts->key))) { 00143 if (!(buf = ast_calloc(1, init_size))) 00144 return NULL; 00145 pthread_setspecific(ts->key, buf); 00146 } 00147 00148 return buf; 00149 } 00150 ) 00151 #else /* defined(DEBUG_THREADLOCALS) */ 00152 AST_INLINE_API( 00153 void *__ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size, const char *file, const char *function, unsigned int line), 00154 { 00155 void *buf; 00156 00157 pthread_once(&ts->once, ts->key_init); 00158 if (!(buf = pthread_getspecific(ts->key))) { 00159 if (!(buf = ast_calloc(1, init_size))) 00160 return NULL; 00161 pthread_setspecific(ts->key, buf); 00162 __ast_threadstorage_object_add(buf, init_size, file, function, line); 00163 } 00164 00165 return buf; 00166 } 00167 ) 00168 00169 #define ast_threadstorage_get(ts, init_size) __ast_threadstorage_get(ts, init_size, __FILE__, __PRETTY_FUNCTION__, __LINE__) 00170 #endif /* defined(DEBUG_THREADLOCALS) */ 00171 00172 /*! 00173 * \brief A dynamic length string 00174 */ 00175 struct ast_dynamic_str { 00176 /* The current maximum length of the string */ 00177 size_t len; 00178 /* The string buffer */ 00179 char str[0]; 00180 }; 00181 00182 /*! 00183 * \brief Create a dynamic length string 00184 * 00185 * \arg init_len This is the initial length of the string buffer 00186 * 00187 * \return This function returns a pointer to the dynamic string length. The 00188 * result will be NULL in the case of a memory allocation error. 00189 * 00190 * /note The result of this function is dynamically allocated memory, and must 00191 * be free()'d after it is no longer needed. 00192 */ 00193 AST_INLINE_API( 00194 struct ast_dynamic_str * attribute_malloc ast_dynamic_str_create(size_t init_len), 00195 { 00196 struct ast_dynamic_str *buf; 00197 00198 if (!(buf = ast_calloc(1, sizeof(*buf) + init_len))) 00199 return NULL; 00200 00201 buf->len = init_len; 00202 00203 return buf; 00204 } 00205 ) 00206 00207 /*! 00208 * \brief Retrieve a thread locally stored dynamic string 00209 * 00210 * \arg ts This is a pointer to the thread storage structure declared by using 00211 * the AST_THREADSTORAGE macro. If declared with 00212 * AST_THREADSTORAGE(my_buf, my_buf_init), then this argument would be 00213 * (&my_buf). 00214 * \arg init_len This is the initial length of the thread's dynamic string. The 00215 * current length may be bigger if previous operations in this thread have 00216 * caused it to increase. 00217 * 00218 * \return This function will return the thread locally storaged dynamic string 00219 * associated with the thread storage management variable passed as the 00220 * first argument. 00221 * The result will be NULL in the case of a memory allocation error. 00222 * 00223 * Example usage: 00224 * \code 00225 * AST_THREADSTORAGE(my_str, my_str_init); 00226 * #define MY_STR_INIT_SIZE 128 00227 * ... 00228 * void my_func(const char *fmt, ...) 00229 * { 00230 * struct ast_dynamic_str *buf; 00231 * 00232 * if (!(buf = ast_dynamic_str_thread_get(&my_str, MY_STR_INIT_SIZE))) 00233 * return; 00234 * ... 00235 * } 00236 * \endcode 00237 */ 00238 #if !defined(DEBUG_THREADLOCALS) 00239 AST_INLINE_API( 00240 struct ast_dynamic_str *ast_dynamic_str_thread_get(struct ast_threadstorage *ts, 00241 size_t init_len), 00242 { 00243 struct ast_dynamic_str *buf; 00244 00245 if (!(buf = ast_threadstorage_get(ts, sizeof(*buf) + init_len))) 00246 return NULL; 00247 00248 if (!buf->len) 00249 buf->len = init_len; 00250 00251 return buf; 00252 } 00253 ) 00254 #else /* defined(DEBUG_THREADLOCALS) */ 00255 AST_INLINE_API( 00256 struct ast_dynamic_str *__ast_dynamic_str_thread_get(struct ast_threadstorage *ts, 00257 size_t init_len, const char *file, const char *function, unsigned int line), 00258 { 00259 struct ast_dynamic_str *buf; 00260 00261 if (!(buf = __ast_threadstorage_get(ts, sizeof(*buf) + init_len, file, function, line))) 00262 return NULL; 00263 00264 if (!buf->len) 00265 buf->len = init_len; 00266 00267 return buf; 00268 } 00269 ) 00270 00271 #define ast_dynamic_str_thread_get(ts, init_len) __ast_dynamic_str_thread_get(ts, init_len, __FILE__, __PRETTY_FUNCTION__, __LINE__) 00272 #endif /* defined(DEBUG_THREADLOCALS) */ 00273 00274 /*! 00275 * \brief Error codes from ast_dynamic_str_thread_build_va() 00276 */ 00277 enum { 00278 /*! An error has occured and the contents of the dynamic string 00279 * are undefined */ 00280 AST_DYNSTR_BUILD_FAILED = -1, 00281 /*! The buffer size for the dynamic string had to be increased, and 00282 * ast_dynamic_str_thread_build_va() needs to be called again after 00283 * a va_end() and va_start(). 00284 */ 00285 AST_DYNSTR_BUILD_RETRY = -2 00286 }; 00287 00288 /*! 00289 * \brief Set a thread locally stored dynamic string from a va_list 00290 * 00291 * \arg buf This is the address of a pointer to an ast_dynamic_str which should 00292 * have been retrieved using ast_dynamic_str_thread_get. It will need to 00293 * be updated in the case that the buffer has to be reallocated to 00294 * accomodate a longer string than what it currently has space for. 00295 * \arg max_len This is the maximum length to allow the string buffer to grow 00296 * to. If this is set to 0, then there is no maximum length. 00297 * \arg ts This is a pointer to the thread storage structure declared by using 00298 * the AST_THREADSTORAGE macro. If declared with 00299 * AST_THREADSTORAGE(my_buf, my_buf_init), then this argument would be 00300 * (&my_buf). 00301 * \arg fmt This is the format string (printf style) 00302 * \arg ap This is the va_list 00303 * 00304 * \return The return value of this function is the same as that of the printf 00305 * family of functions. 00306 * 00307 * Example usage: 00308 * \code 00309 * AST_THREADSTORAGE(my_str, my_str_init); 00310 * #define MY_STR_INIT_SIZE 128 00311 * ... 00312 * void my_func(const char *fmt, ...) 00313 * { 00314 * struct ast_dynamic_str *buf; 00315 * va_list ap; 00316 * 00317 * if (!(buf = ast_dynamic_str_thread_get(&my_str, MY_STR_INIT_SIZE))) 00318 * return; 00319 * ... 00320 * va_start(fmt, ap); 00321 * ast_dynamic_str_thread_set_va(&buf, 0, &my_str, fmt, ap); 00322 * va_end(ap); 00323 * 00324 * printf("This is the string we just built: %s\n", buf->str); 00325 * ... 00326 * } 00327 * \endcode 00328 */ 00329 #define ast_dynamic_str_thread_set_va(buf, max_len, ts, fmt, ap) \ 00330 ({ \ 00331 int __res; \ 00332 while ((__res = ast_dynamic_str_thread_build_va(buf, max_len, \ 00333 ts, 0, fmt, ap)) == AST_DYNSTR_BUILD_RETRY) { \ 00334 va_end(ap); \ 00335 va_start(ap, fmt); \ 00336 } \ 00337 (__res); \ 00338 }) 00339 00340 /*! 00341 * \brief Append to a thread local dynamic string using a va_list 00342 * 00343 * The arguments, return values, and usage of this are the same as those for 00344 * ast_dynamic_str_thread_set_va(). However, instead of setting a new value 00345 * for the string, this will append to the current value. 00346 */ 00347 #define ast_dynamic_str_thread_append_va(buf, max_len, ts, fmt, ap) \ 00348 ({ \ 00349 int __res; \ 00350 while ((__res = ast_dynamic_str_thread_build_va(buf, max_len, \ 00351 ts, 1, fmt, ap)) == AST_DYNSTR_BUILD_RETRY) { \ 00352 va_end(ap); \ 00353 va_start(ap, fmt); \ 00354 } \ 00355 (__res); \ 00356 }) 00357 00358 /*! 00359 * \brief Core functionality of ast_dynamic_str_thread_(set|append)_va 00360 * 00361 * The arguments to this function are the same as those described for 00362 * ast_dynamic_str_thread_set_va except for an addition argument, append. 00363 * If append is non-zero, this will append to the current string instead of 00364 * writing over it. 00365 */ 00366 int ast_dynamic_str_thread_build_va(struct ast_dynamic_str **buf, size_t max_len, 00367 struct ast_threadstorage *ts, int append, const char *fmt, va_list ap) __attribute__((format(printf, 5, 0))); 00368 00369 /*! 00370 * \brief Set a thread locally stored dynamic string using variable arguments 00371 * 00372 * \arg buf This is the address of a pointer to an ast_dynamic_str which should 00373 * have been retrieved using ast_dynamic_str_thread_get. It will need to 00374 * be updated in the case that the buffer has to be reallocated to 00375 * accomodate a longer string than what it currently has space for. 00376 * \arg max_len This is the maximum length to allow the string buffer to grow 00377 * to. If this is set to 0, then there is no maximum length. 00378 * \arg ts This is a pointer to the thread storage structure declared by using 00379 * the AST_THREADSTORAGE macro. If declared with 00380 * AST_THREADSTORAGE(my_buf, my_buf_init), then this argument would be 00381 * (&my_buf). 00382 * \arg fmt This is the format string (printf style) 00383 * 00384 * \return The return value of this function is the same as that of the printf 00385 * family of functions. 00386 * 00387 * Example usage: 00388 * \code 00389 * AST_THREADSTORAGE(my_str, my_str_init); 00390 * #define MY_STR_INIT_SIZE 128 00391 * ... 00392 * void my_func(int arg1, int arg2) 00393 * { 00394 * struct ast_dynamic_str *buf; 00395 * va_list ap; 00396 * 00397 * if (!(buf = ast_dynamic_str_thread_get(&my_str, MY_STR_INIT_SIZE))) 00398 * return; 00399 * ... 00400 * ast_dynamic_str_thread_set(&buf, 0, &my_str, "arg1: %d arg2: %d\n", 00401 * arg1, arg2); 00402 * 00403 * printf("This is the string we just built: %s\n", buf->str); 00404 * ... 00405 * } 00406 * \endcode 00407 */ 00408 AST_INLINE_API( 00409 int __attribute__((format(printf, 4, 5))) ast_dynamic_str_thread_set( 00410 struct ast_dynamic_str **buf, size_t max_len, 00411 struct ast_threadstorage *ts, const char *fmt, ...), 00412 { 00413 int res; 00414 va_list ap; 00415 00416 va_start(ap, fmt); 00417 res = ast_dynamic_str_thread_set_va(buf, max_len, ts, fmt, ap); 00418 va_end(ap); 00419 00420 return res; 00421 } 00422 ) 00423 00424 /*! 00425 * \brief Append to a thread local dynamic string 00426 * 00427 * The arguments, return values, and usage of this function are the same as 00428 * ast_dynamic_str_thread_set(). However, instead of setting a new value for 00429 * the string, this function appends to the current value. 00430 */ 00431 AST_INLINE_API( 00432 int __attribute__((format(printf, 4, 5))) ast_dynamic_str_thread_append( 00433 struct ast_dynamic_str **buf, size_t max_len, 00434 struct ast_threadstorage *ts, const char *fmt, ...), 00435 { 00436 int res; 00437 va_list ap; 00438 00439 va_start(ap, fmt); 00440 res = ast_dynamic_str_thread_append_va(buf, max_len, ts, fmt, ap); 00441 va_end(ap); 00442 00443 return res; 00444 } 00445 ) 00446 00447 /*! 00448 * \brief Set a dynamic string 00449 * 00450 * \arg buf This is the address of a pointer to an ast_dynamic_str. It will 00451 * need to be updated in the case that the buffer has to be reallocated to 00452 * accomodate a longer string than what it currently has space for. 00453 * \arg max_len This is the maximum length to allow the string buffer to grow 00454 * to. If this is set to 0, then there is no maximum length. 00455 * 00456 * \return The return value of this function is the same as that of the printf 00457 * family of functions. 00458 */ 00459 AST_INLINE_API( 00460 int __attribute__((format(printf, 3, 4))) ast_dynamic_str_set( 00461 struct ast_dynamic_str **buf, size_t max_len, 00462 const char *fmt, ...), 00463 { 00464 int res; 00465 va_list ap; 00466 00467 va_start(ap, fmt); 00468 res = ast_dynamic_str_thread_set_va(buf, max_len, NULL, fmt, ap); 00469 va_end(ap); 00470 00471 return res; 00472 } 00473 ) 00474 00475 /*! 00476 * \brief Append to a dynatic string 00477 * 00478 * The arguments, return values, and usage of this function are the same as 00479 * ast_dynamic_str_set(). However, this function appends to the string instead 00480 * of setting a new value. 00481 */ 00482 AST_INLINE_API( 00483 int __attribute__((format(printf, 3, 4))) ast_dynamic_str_append( 00484 struct ast_dynamic_str **buf, size_t max_len, 00485 const char *fmt, ...), 00486 { 00487 int res; 00488 va_list ap; 00489 00490 va_start(ap, fmt); 00491 res = ast_dynamic_str_thread_append_va(buf, max_len, NULL, fmt, ap); 00492 va_end(ap); 00493 00494 return res; 00495 } 00496 ) 00497 00498 #endif /* ASTERISK_THREADSTORAGE_H */