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