mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-04 12:12:48 +00:00
Add a more efficient way of allocating structures that use stringfields
This commit adds an API call that can be used to allocate a structure along with this stringfield storage in a single allocation. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@192362 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -138,6 +138,7 @@ struct ast_string_field_pool {
|
|||||||
*/
|
*/
|
||||||
struct ast_string_field_mgr {
|
struct ast_string_field_mgr {
|
||||||
ast_string_field last_alloc; /*!< the last field allocated */
|
ast_string_field last_alloc; /*!< the last field allocated */
|
||||||
|
struct ast_string_field_pool *embedded_pool; /*!< pointer to the embedded pool, if any */
|
||||||
#if defined(__AST_DEBUG_MALLOC)
|
#if defined(__AST_DEBUG_MALLOC)
|
||||||
const char *owner_file; /*!< filename of owner */
|
const char *owner_file; /*!< filename of owner */
|
||||||
const char *owner_func; /*!< function name of owner */
|
const char *owner_func; /*!< function name of owner */
|
||||||
@@ -253,6 +254,30 @@ void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
|
|||||||
int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
|
int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
|
||||||
int needed, const char *file, int lineno, const char *func);
|
int needed, const char *file, int lineno, const char *func);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Allocate a structure with embedded stringfields in a single allocation
|
||||||
|
* \param n Number of structures to allocate (see ast_calloc)
|
||||||
|
* \param type The type of structure to allocate
|
||||||
|
* \param size The number of bytes of space (minimum) to allocate for stringfields to use
|
||||||
|
*
|
||||||
|
* This function will allocate memory for one or more structures that use stringfields, and
|
||||||
|
* also allocate space for the stringfields and initialize the stringfield management
|
||||||
|
* structure embedded in the outer structure.
|
||||||
|
*
|
||||||
|
* \since 1.6.3
|
||||||
|
*/
|
||||||
|
#define ast_calloc_with_stringfields(n, type, size) \
|
||||||
|
__ast_calloc_with_stringfields(n, sizeof(type), offsetof(type, __field_mgr), offsetof(type, __field_mgr_pool), \
|
||||||
|
size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief internal version of ast_calloc_with_stringfields
|
||||||
|
*/
|
||||||
|
void * attribute_malloc __ast_calloc_with_stringfields(unsigned int num_structs, size_t struct_size, size_t field_mgr_offset,
|
||||||
|
size_t field_mgr_pool_offset, size_t pool_size, const char *file,
|
||||||
|
int lineno, const char *func);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
\brief Release a field's allocation from a pool
|
\brief Release a field's allocation from a pool
|
||||||
|
49
main/utils.c
49
main/utils.c
@@ -1530,6 +1530,8 @@ static int add_string_pool(struct ast_string_field_mgr *mgr, struct ast_string_f
|
|||||||
* size > 0 means initialize the pool list with a pool of given size.
|
* size > 0 means initialize the pool list with a pool of given size.
|
||||||
* This must be called right after allocating the object.
|
* This must be called right after allocating the object.
|
||||||
* size = 0 means release all pools except the most recent one.
|
* size = 0 means release all pools except the most recent one.
|
||||||
|
* If the first pool was allocated via embedding in another
|
||||||
|
* object, that pool will be preserved instead.
|
||||||
* This is useful to e.g. reset an object to the initial value.
|
* This is useful to e.g. reset an object to the initial value.
|
||||||
* size < 0 means release all pools.
|
* size < 0 means release all pools.
|
||||||
* This must be done before destroying the object.
|
* This must be done before destroying the object.
|
||||||
@@ -1559,6 +1561,9 @@ int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_
|
|||||||
|
|
||||||
if (needed < 0) { /* reset all pools */
|
if (needed < 0) { /* reset all pools */
|
||||||
/* nothing to do */
|
/* nothing to do */
|
||||||
|
} else if (mgr->embedded_pool) { /* preserve the embedded pool */
|
||||||
|
preserve = mgr->embedded_pool;
|
||||||
|
cur = *pool_head;
|
||||||
} else { /* preserve the last pool */
|
} else { /* preserve the last pool */
|
||||||
if (*pool_head == NULL) {
|
if (*pool_head == NULL) {
|
||||||
ast_log(LOG_WARNING, "trying to reset empty pool\n");
|
ast_log(LOG_WARNING, "trying to reset empty pool\n");
|
||||||
@@ -1736,6 +1741,50 @@ void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
|
|||||||
va_end(ap1);
|
va_end(ap1);
|
||||||
va_end(ap2);
|
va_end(ap2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *__ast_calloc_with_stringfields(unsigned int num_structs, size_t struct_size, size_t field_mgr_offset,
|
||||||
|
size_t field_mgr_pool_offset, size_t pool_size, const char *file,
|
||||||
|
int lineno, const char *func)
|
||||||
|
{
|
||||||
|
struct ast_string_field_mgr *mgr;
|
||||||
|
struct ast_string_field_pool *pool;
|
||||||
|
struct ast_string_field_pool **pool_head;
|
||||||
|
size_t pool_size_needed = sizeof(*pool) + pool_size;
|
||||||
|
size_t size_to_alloc = optimal_alloc_size(struct_size + pool_size_needed);
|
||||||
|
void *allocation;
|
||||||
|
unsigned int x;
|
||||||
|
|
||||||
|
#if defined(__AST_DEBUG_MALLOC)
|
||||||
|
if (!(allocation = __ast_calloc(num_structs, size_to_alloc, file, lineno, func))) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (!(allocation = ast_calloc(num_structs, size_to_alloc))) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (x = 0; x < num_structs; x++) {
|
||||||
|
void *base = allocation + (size_to_alloc * x);
|
||||||
|
const char **p;
|
||||||
|
|
||||||
|
mgr = base + field_mgr_offset;
|
||||||
|
pool_head = base + field_mgr_pool_offset;
|
||||||
|
pool = base + struct_size;
|
||||||
|
|
||||||
|
p = (const char **) pool_head + 1;
|
||||||
|
while ((struct ast_string_field_mgr *) p != mgr) {
|
||||||
|
*p++ = __ast_string_field_empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
mgr->embedded_pool = pool;
|
||||||
|
*pool_head = pool;
|
||||||
|
pool->size = size_to_alloc - struct_size - sizeof(*pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
return allocation;
|
||||||
|
}
|
||||||
|
|
||||||
/* end of stringfields support */
|
/* end of stringfields support */
|
||||||
|
|
||||||
AST_MUTEX_DEFINE_STATIC(fetchadd_m); /* used for all fetc&add ops */
|
AST_MUTEX_DEFINE_STATIC(fetchadd_m); /* used for all fetc&add ops */
|
||||||
|
Reference in New Issue
Block a user