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