Skip to content
Snippets Groups Projects
Commit 2746f589 authored by Kevin P. Fleming's avatar Kevin P. Fleming
Browse files

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
parent 1f49e675
No related branches found
No related tags found
No related merge requests found
......@@ -138,6 +138,7 @@ struct ast_string_field_pool {
*/
struct ast_string_field_mgr {
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)
const char *owner_file; /*!< filename 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 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
\brief Release a field's allocation from a pool
......
......@@ -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.
* This must be called right after allocating the object.
* 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.
* size < 0 means release all pools.
* 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 */
/* nothing to do */
} else if (mgr->embedded_pool) { /* preserve the embedded pool */
preserve = mgr->embedded_pool;
cur = *pool_head;
} else { /* preserve the last pool */
if (*pool_head == NULL) {
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(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 */
AST_MUTEX_DEFINE_STATIC(fetchadd_m); /* used for all fetc&add ops */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment