*/
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 */
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
\param pool_head Pointer to the current pool
* 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.
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");
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 */