- Fix a few spelling mistakes.
[asterisk/asterisk.git] / include / asterisk / threadstorage.h
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2006, Digium, Inc.
5  *
6  * Russell Bryant <russell@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*!
20  * \file threadstorage.h
21  * \author Russell Bryant <russell@digium.com>
22  * \brief Definitions to aid in the use of thread local storage
23  */
24
25 /*!
26  * \page AstThreadStorage The Asterisk Thread Storage API
27  *
28  *
29  * The POSIX threads (pthreads) API provides the ability to define thread
30  * specific data.  The functions and structures defined here are intended
31  * to centralize the code that is commonly used when using thread local
32  * storage.
33  *
34  * The motivation for using this code in Asterisk is for situations where
35  * storing data on a thread-specific basis can provide some amount of
36  * performance benefit.  For example, there are some call types in Asterisk
37  * where ast_frame structures must be allocated very rapidly (easily 50, 100,
38  * 200 times a second).  Instead of doing the equivalent of that many calls
39  * to malloc() and free() per second, thread local storage is used to keep a
40  * list of unused frame structures so that they can be continuously reused.
41  *
42  * - \ref threadstorage.h
43  */
44
45 #ifndef ASTERISK_THREADSTORAGE_H
46 #define ASTERISK_THREADSTORAGE_H
47
48 #include <pthread.h>
49
50 #include "asterisk/utils.h"
51 #include "asterisk/inline_api.h"
52
53 /*!
54  * \brief data for a thread locally stored variable
55  */
56 struct ast_threadstorage {
57         /*! Ensure that the key is only initialized by one thread */
58         pthread_once_t once;
59         /*! The key used to retrieve this thread's data */
60         pthread_key_t key;
61         /*! The function that initializes the key */
62         void (*key_init)(void);
63         /*! Custom initialization function specific to the object */
64         int (*custom_init)(void *);
65 };
66
67 /*!
68  * \brief Define a thread storage variable
69  *
70  * \arg name The name of the thread storage object
71  *
72  * This macro would be used to declare an instance of thread storage in a file.
73  *
74  * Example usage:
75  * \code
76  * AST_THREADSTORAGE(my_buf);
77  * \endcode
78  */
79 #define AST_THREADSTORAGE(name) \
80         AST_THREADSTORAGE_CUSTOM(name, NULL, ast_free) 
81
82 /*!
83  * \brief Define a thread storage variable, with custom initialization and cleanup
84  *
85  * \arg name The name of the thread storage object
86  * \arg init This is a custom function that will be called after each thread specific
87  *           object is allocated, with the allocated block of memory passed
88  *           as the argument.
89  * \arg cleanup This is a custom function that will be called instead of ast_free
90  *              when the thread goes away.  Note that if this is used, it *MUST*
91  *              call free on the allocated memory.
92  *
93  * Example usage:
94  * \code
95  * AST_THREADSTORAGE_CUSTOM(my_buf, my_init, my_cleanup);
96  * \endcode
97  */
98 #define AST_THREADSTORAGE_CUSTOM(name, c_init, c_cleanup) \
99 static void init_##name(void);                            \
100 static struct ast_threadstorage name = {                  \
101         .once = PTHREAD_ONCE_INIT,                        \
102         .key_init = init_##name,                          \
103         .custom_init = c_init,                            \
104 };                                                        \
105 static void init_##name(void)                             \
106 {                                                         \
107         pthread_key_create(&(name).key, c_cleanup);       \
108 }
109
110 /*!
111  * \brief Retrieve thread storage
112  *
113  * \arg ts This is a pointer to the thread storage structure declared by using
114  *      the AST_THREADSTORAGE macro.  If declared with 
115  *      AST_THREADSTORAGE(my_buf, my_buf_init), then this argument would be 
116  *      (&my_buf).
117  * \arg init_size This is the amount of space to be allocated the first time
118  *      this thread requests its data. Thus, this should be the size that the
119  *      code accessing this thread storage is assuming the size to be.
120  *
121  * \return This function will return the thread local storage associated with
122  *         the thread storage management variable passed as the first argument.
123  *         The result will be NULL in the case of a memory allocation error.
124  *
125  * Example usage:
126  * \code
127  * AST_THREADSTORAGE(my_buf, my_buf_init);
128  * #define MY_BUF_SIZE   128
129  * ...
130  * void my_func(const char *fmt, ...)
131  * {
132  *      void *buf;
133  *
134  *      if (!(buf = ast_threadstorage_get(&my_buf, MY_BUF_SIZE)))
135  *           return;
136  *      ...
137  * }
138  * \endcode
139  */
140 AST_INLINE_API(
141 void *ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size),
142 {
143         void *buf;
144
145         pthread_once(&ts->once, ts->key_init);
146         if (!(buf = pthread_getspecific(ts->key))) {
147                 if (!(buf = ast_calloc(1, init_size)))
148                         return NULL;
149                 if (ts->custom_init && ts->custom_init(buf)) {
150                         free(buf);
151                         return NULL;
152                 }
153                 pthread_setspecific(ts->key, buf);
154         }
155
156         return buf;
157 }
158 )
159
160 void __ast_threadstorage_cleanup(void *);
161
162 /*!
163  * \brief A dynamic length string
164  */
165 struct ast_dynamic_str {
166         /* The current maximum length of the string */
167         size_t len;
168         /* The string buffer */
169         char str[0];
170 };
171
172 /*!
173  * \brief Create a dynamic length string
174  *
175  * \arg init_len This is the initial length of the string buffer
176  *
177  * \return This function returns a pointer to the dynamic string length.  The
178  *         result will be NULL in the case of a memory allocation error.
179  *
180  * /note The result of this function is dynamically allocated memory, and must
181  *       be free()'d after it is no longer needed.
182  */
183 AST_INLINE_API(
184 struct ast_dynamic_str * attribute_malloc ast_dynamic_str_create(size_t init_len),
185 {
186         struct ast_dynamic_str *buf;
187
188         if (!(buf = ast_calloc(1, sizeof(*buf) + init_len)))
189                 return NULL;
190         
191         buf->len = init_len;
192
193         return buf;
194 }
195 )
196
197 /*!
198  * \brief Retrieve a thread locally stored dynamic string
199  *
200  * \arg ts This is a pointer to the thread storage structure declared by using
201  *      the AST_THREADSTORAGE macro.  If declared with 
202  *      AST_THREADSTORAGE(my_buf, my_buf_init), then this argument would be 
203  *      (&my_buf).
204  * \arg init_len This is the initial length of the thread's dynamic string. The
205  *      current length may be bigger if previous operations in this thread have
206  *      caused it to increase.
207  *
208  * \return This function will return the thread locally stored dynamic string
209  *         associated with the thread storage management variable passed as the
210  *         first argument.
211  *         The result will be NULL in the case of a memory allocation error.
212  *
213  * Example usage:
214  * \code
215  * AST_THREADSTORAGE(my_str, my_str_init);
216  * #define MY_STR_INIT_SIZE   128
217  * ...
218  * void my_func(const char *fmt, ...)
219  * {
220  *      struct ast_dynamic_str *buf;
221  *
222  *      if (!(buf = ast_dynamic_str_thread_get(&my_str, MY_STR_INIT_SIZE)))
223  *           return;
224  *      ...
225  * }
226  * \endcode
227  */
228 AST_INLINE_API(
229 struct ast_dynamic_str *ast_dynamic_str_thread_get(struct ast_threadstorage *ts,
230         size_t init_len),
231 {
232         struct ast_dynamic_str *buf;
233
234         if (!(buf = ast_threadstorage_get(ts, sizeof(*buf) + init_len)))
235                 return NULL;
236         
237         if (!buf->len)
238                 buf->len = init_len;
239
240         return buf;
241 }
242 )
243
244 /*!
245  * \brief Error codes from ast_dynamic_str_thread_build_va()
246  */
247 enum {
248         /*! An error has occured and the contents of the dynamic string
249          *  are undefined */
250         AST_DYNSTR_BUILD_FAILED = -1,
251         /*! The buffer size for the dynamic string had to be increased, and
252          *  ast_dynamic_str_thread_build_va() needs to be called again after
253          *  a va_end() and va_start().
254          */
255         AST_DYNSTR_BUILD_RETRY = -2
256 };
257
258 /*!
259  * \brief Set a thread locally stored dynamic string from a va_list
260  *
261  * \arg buf This is the address of a pointer to an ast_dynamic_str which should
262  *      have been retrieved using ast_dynamic_str_thread_get.  It will need to
263  *      be updated in the case that the buffer has to be reallocated to
264  *      accommodate a longer string than what it currently has space for.
265  * \arg max_len This is the maximum length to allow the string buffer to grow
266  *      to.  If this is set to 0, then there is no maximum length.
267  * \arg ts This is a pointer to the thread storage structure declared by using
268  *      the AST_THREADSTORAGE macro.  If declared with 
269  *      AST_THREADSTORAGE(my_buf, my_buf_init), then this argument would be 
270  *      (&my_buf).
271  * \arg fmt This is the format string (printf style)
272  * \arg ap This is the va_list
273  *
274  * \return The return value of this function is the same as that of the printf
275  *         family of functions.
276  *
277  * Example usage:
278  * \code
279  * AST_THREADSTORAGE(my_str, my_str_init);
280  * #define MY_STR_INIT_SIZE   128
281  * ...
282  * void my_func(const char *fmt, ...)
283  * {
284  *      struct ast_dynamic_str *buf;
285  *      va_list ap;
286  *
287  *      if (!(buf = ast_dynamic_str_thread_get(&my_str, MY_STR_INIT_SIZE)))
288  *           return;
289  *      ...
290  *      va_start(fmt, ap);
291  *      ast_dynamic_str_thread_set_va(&buf, 0, &my_str, fmt, ap);
292  *      va_end(ap);
293  * 
294  *      printf("This is the string we just built: %s\n", buf->str);
295  *      ...
296  * }
297  * \endcode
298  */
299 #define ast_dynamic_str_thread_set_va(buf, max_len, ts, fmt, ap)                 \
300         ({                                                                       \
301                 int __res;                                                       \
302                 while ((__res = ast_dynamic_str_thread_build_va(buf, max_len,    \
303                         ts, 0, fmt, ap)) == AST_DYNSTR_BUILD_RETRY) {            \
304                         va_end(ap);                                              \
305                         va_start(ap, fmt);                                       \
306                 }                                                                \
307                 (__res);                                                         \
308         })
309
310 /*!
311  * \brief Append to a thread local dynamic string using a va_list
312  *
313  * The arguments, return values, and usage of this are the same as those for
314  * ast_dynamic_str_thread_set_va().  However, instead of setting a new value
315  * for the string, this will append to the current value.
316  */
317 #define ast_dynamic_str_thread_append_va(buf, max_len, ts, fmt, ap)              \
318         ({                                                                       \
319                 int __res;                                                       \
320                 while ((__res = ast_dynamic_str_thread_build_va(buf, max_len,    \
321                         ts, 1, fmt, ap)) == AST_DYNSTR_BUILD_RETRY) {            \
322                         va_end(ap);                                              \
323                         va_start(ap, fmt);                                       \
324                 }                                                                \
325                 (__res);                                                         \
326         })
327
328 /*!
329  * \brief Core functionality of ast_dynamic_str_thread_(set|append)_va
330  *
331  * The arguments to this function are the same as those described for
332  * ast_dynamic_str_thread_set_va except for an addition argument, append.
333  * If append is non-zero, this will append to the current string instead of
334  * writing over it.
335  *
336  * In the case that this function is called and the buffer was not large enough
337  * to hold the result, the partial write will be truncated, and the result
338  * AST_DYNSTR_BUILD_RETRY will be returned to indicate that the buffer size
339  * was increased, and the function should be called a second time.
340  *
341  * A return of AST_DYNSTR_BUILD_FAILED indicates a memory allocation error.
342  *
343  * A return value greater than or equal to zero indicates the number of
344  * characters that have been written, not including the terminating '\0'.
345  * In the append case, this only includes the number of characters appended.
346  *
347  * \note This function should never need to be called directly.  It should
348  *       through calling one of the other functions or macros defined in this
349  *       file.
350  */
351 int ast_dynamic_str_thread_build_va(struct ast_dynamic_str **buf, size_t max_len,
352         struct ast_threadstorage *ts, int append, const char *fmt, va_list ap);
353
354 /*!
355  * \brief Set a thread locally stored dynamic string using variable arguments
356  *
357  * \arg buf This is the address of a pointer to an ast_dynamic_str which should
358  *      have been retrieved using ast_dynamic_str_thread_get.  It will need to
359  *      be updated in the case that the buffer has to be reallocated to
360  *      accomodate a longer string than what it currently has space for.
361  * \arg max_len This is the maximum length to allow the string buffer to grow
362  *      to.  If this is set to 0, then there is no maximum length.
363  * \arg ts This is a pointer to the thread storage structure declared by using
364  *      the AST_THREADSTORAGE macro.  If declared with 
365  *      AST_THREADSTORAGE(my_buf, my_buf_init), then this argument would be 
366  *      (&my_buf).
367  * \arg fmt This is the format string (printf style)
368  *
369  * \return The return value of this function is the same as that of the printf
370  *         family of functions.
371  *
372  * Example usage:
373  * \code
374  * AST_THREADSTORAGE(my_str, my_str_init);
375  * #define MY_STR_INIT_SIZE   128
376  * ...
377  * void my_func(int arg1, int arg2)
378  * {
379  *      struct ast_dynamic_str *buf;
380  *      va_list ap;
381  *
382  *      if (!(buf = ast_dynamic_str_thread_get(&my_str, MY_STR_INIT_SIZE)))
383  *           return;
384  *      ...
385  *      ast_dynamic_str_thread_set(&buf, 0, &my_str, "arg1: %d  arg2: %d\n",
386  *           arg1, arg2);
387  * 
388  *      printf("This is the string we just built: %s\n", buf->str);
389  *      ...
390  * }
391  * \endcode
392  */
393 AST_INLINE_API(
394 int __attribute__ ((format (printf, 4, 5))) ast_dynamic_str_thread_set(
395         struct ast_dynamic_str **buf, size_t max_len, 
396         struct ast_threadstorage *ts, const char *fmt, ...),
397 {
398         int res;
399         va_list ap;
400
401         va_start(ap, fmt);
402         res = ast_dynamic_str_thread_set_va(buf, max_len, ts, fmt, ap);
403         va_end(ap);
404
405         return res;
406 }
407 )
408
409 /*!
410  * \brief Append to a thread local dynamic string
411  *
412  * The arguments, return values, and usage of this function are the same as
413  * ast_dynamic_str_thread_set().  However, instead of setting a new value for
414  * the string, this function appends to the current value.
415  */
416 AST_INLINE_API(
417 int __attribute__ ((format (printf, 4, 5))) ast_dynamic_str_thread_append(
418         struct ast_dynamic_str **buf, size_t max_len, 
419         struct ast_threadstorage *ts, const char *fmt, ...),
420 {
421         int res;
422         va_list ap;
423
424         va_start(ap, fmt);
425         res = ast_dynamic_str_thread_append_va(buf, max_len, ts, fmt, ap);
426         va_end(ap);
427
428         return res;
429 }
430 )
431
432 /*!
433  * \brief Set a dynamic string
434  *
435  * \arg buf This is the address of a pointer to an ast_dynamic_str.  It will
436  *      need to be updated in the case that the buffer has to be reallocated to
437  *      accommodate a longer string than what it currently has space for.
438  * \arg max_len This is the maximum length to allow the string buffer to grow
439  *      to.  If this is set to 0, then there is no maximum length.
440  *
441  * \return The return value of this function is the same as that of the printf
442  *         family of functions.
443  */
444 AST_INLINE_API(
445 int __attribute__ ((format (printf, 3, 4))) ast_dynamic_str_set(
446         struct ast_dynamic_str **buf, size_t max_len,
447         const char *fmt, ...),
448 {
449         int res;
450         va_list ap;
451         
452         va_start(ap, fmt);
453         res = ast_dynamic_str_thread_set_va(buf, max_len, NULL, fmt, ap);
454         va_end(ap);
455
456         return res;
457 }
458 )
459
460 /*!
461  * \brief Append to a dynamic string
462  *
463  * The arguments, return values, and usage of this function are the same as
464  * ast_dynamic_str_set().  However, this function appends to the string instead
465  * of setting a new value.
466  */
467 AST_INLINE_API(
468 int __attribute__ ((format (printf, 3, 4))) ast_dynamic_str_append(
469         struct ast_dynamic_str **buf, size_t max_len,
470         const char *fmt, ...),
471 {
472         int res;
473         va_list ap;
474         
475         va_start(ap, fmt);
476         res = ast_dynamic_str_thread_append_va(buf, max_len, NULL, fmt, ap);
477         va_end(ap);
478
479         return res;
480 }
481 )
482
483 #endif /* ASTERISK_THREADSTORAGE_H */