📄 threadstorage.h
字号:
/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 2006, Digium, Inc. * * Russell Bryant <russell@digium.com> * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. *//*! * \file threadstorage.h * \author Russell Bryant <russell@digium.com> * * \brief Definitions to aid in the use of thread local storage*/#ifndef ASTERISK_THREADSTORAGE_H#define ASTERISK_THREADSTORAGE_H#include <pthread.h>#include "asterisk/utils.h"#include "asterisk/inline_api.h"/*! * \brief data for a thread locally stored variable */struct ast_threadstorage { /*! Ensure that the key is only initialized by one thread */ pthread_once_t once; /*! The key used to retrieve this thread's data */ pthread_key_t key; /*! The function that initializes the key */ void (*key_init)(void);};#if defined(DEBUG_THREADLOCALS)void __ast_threadstorage_object_add(void *key, size_t len, const char *file, const char *function, unsigned int line);void __ast_threadstorage_object_remove(void *key);void __ast_threadstorage_object_replace(void *key_old, void *key_new, size_t len);#endif /* defined(DEBUG_THREADLOCALS) *//*! * \brief Define a thread storage variable * * \arg name The name of the thread storage * \arg name_init This is a name used to create the function that gets called * to initialize this thread storage. It can be anything since it will not * be referred to anywhere else * * This macro would be used to declare an instance of thread storage in a file. * * Example usage: * \code * AST_THREADSTORAGE(my_buf, my_buf_init); * \endcode */#define AST_THREADSTORAGE(name, name_init) \ AST_THREADSTORAGE_CUSTOM(name, name_init, ast_free) #if !defined(DEBUG_THREADLOCALS)#define AST_THREADSTORAGE_CUSTOM(name, name_init, cleanup) \static void name_init(void); \static struct ast_threadstorage name = { \ .once = PTHREAD_ONCE_INIT, \ .key_init = name_init, \}; \static void name_init(void) \{ \ pthread_key_create(&(name).key, cleanup); \}#else /* defined(DEBUG_THREADLOCALS) */#define AST_THREADSTORAGE_CUSTOM(name, name_init, cleanup) \static void name_init(void); \static struct ast_threadstorage name = { \ .once = PTHREAD_ONCE_INIT, \ .key_init = name_init, \}; \static void __cleanup_##name(void *data) \{ \ __ast_threadstorage_object_remove(data); \ cleanup(data); \} \static void name_init(void) \{ \ pthread_key_create(&(name).key, __cleanup_##name); \}#endif /* defined(DEBUG_THREADLOCALS) *//*! * \brief Retrieve thread storage * * \arg ts This is a pointer to the thread storage structure declared by using * the AST_THREADSTORAGE macro. If declared with * AST_THREADSTORAGE(my_buf, my_buf_init), then this argument would be * (&my_buf). * \arg init_size This is the amount of space to be allocated the first time * this thread requests its data. Thus, this should be the size that the * code accessing this thread storage is assuming the size to be. * * \return This function will return the thread local storage associated with * the thread storage management variable passed as the first argument. * The result will be NULL in the case of a memory allocation error. * * Example usage: * \code * AST_THREADSTORAGE(my_buf, my_buf_init); * #define MY_BUF_SIZE 128 * ... * void my_func(const char *fmt, ...) * { * void *buf; * * if (!(buf = ast_threadstorage_get(&my_buf, MY_BUF_SIZE))) * return; * ... * } * \endcode */#if !defined(DEBUG_THREADLOCALS)AST_INLINE_API(void *ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size),{ void *buf; pthread_once(&ts->once, ts->key_init); if (!(buf = pthread_getspecific(ts->key))) { if (!(buf = ast_calloc(1, init_size))) return NULL; pthread_setspecific(ts->key, buf); } return buf;})#else /* defined(DEBUG_THREADLOCALS) */AST_INLINE_API(void *__ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size, const char *file, const char *function, unsigned int line),{ void *buf; pthread_once(&ts->once, ts->key_init); if (!(buf = pthread_getspecific(ts->key))) { if (!(buf = ast_calloc(1, init_size))) return NULL; pthread_setspecific(ts->key, buf); __ast_threadstorage_object_add(buf, init_size, file, function, line); } return buf;})#define ast_threadstorage_get(ts, init_size) __ast_threadstorage_get(ts, init_size, __FILE__, __PRETTY_FUNCTION__, __LINE__)#endif /* defined(DEBUG_THREADLOCALS) *//*! * \brief A dynamic length string */struct ast_dynamic_str { /* The current maximum length of the string */ size_t len; /* The string buffer */ char str[0];};/*! * \brief Create a dynamic length string * * \arg init_len This is the initial length of the string buffer * * \return This function returns a pointer to the dynamic string length. The * result will be NULL in the case of a memory allocation error. * * /note The result of this function is dynamically allocated memory, and must * be free()'d after it is no longer needed. */AST_INLINE_API(struct ast_dynamic_str * attribute_malloc ast_dynamic_str_create(size_t init_len),{ struct ast_dynamic_str *buf; if (!(buf = ast_calloc(1, sizeof(*buf) + init_len))) return NULL; buf->len = init_len; return buf;})/*! * \brief Retrieve a thread locally stored dynamic string * * \arg ts This is a pointer to the thread storage structure declared by using * the AST_THREADSTORAGE macro. If declared with * AST_THREADSTORAGE(my_buf, my_buf_init), then this argument would be * (&my_buf). * \arg init_len This is the initial length of the thread's dynamic string. The * current length may be bigger if previous operations in this thread have * caused it to increase. * * \return This function will return the thread locally storaged dynamic string * associated with the thread storage management variable passed as the * first argument. * The result will be NULL in the case of a memory allocation error. * * Example usage: * \code * AST_THREADSTORAGE(my_str, my_str_init); * #define MY_STR_INIT_SIZE 128 * ... * void my_func(const char *fmt, ...) * { * struct ast_dynamic_str *buf; * * if (!(buf = ast_dynamic_str_thread_get(&my_str, MY_STR_INIT_SIZE))) * return; * ... * } * \endcode */#if !defined(DEBUG_THREADLOCALS)AST_INLINE_API(struct ast_dynamic_str *ast_dynamic_str_thread_get(struct ast_threadstorage *ts, size_t init_len),{ struct ast_dynamic_str *buf; if (!(buf = ast_threadstorage_get(ts, sizeof(*buf) + init_len))) return NULL; if (!buf->len) buf->len = init_len; return buf;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -