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