mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 04:11:08 +00:00
minor optimization for stringfields: when a field is being set to a larger value than it currently contains and it happens to be the most recent field allocated from the currentl pool, it is possible to 'grow' it without having to waste the space it is currently using (or potentially even allocate a new pool)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@132872 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -123,6 +123,7 @@ struct ast_string_field_mgr {
|
||||
size_t size; /*!< the total size of the current pool */
|
||||
size_t space; /*!< the space available in the current pool */
|
||||
size_t used; /*!< the space used in the current pool */
|
||||
ast_string_field last_alloc; /*!< the last field allocated */
|
||||
};
|
||||
|
||||
/*!
|
||||
@@ -137,6 +138,24 @@ struct ast_string_field_mgr {
|
||||
int __ast_string_field_init(struct ast_string_field_mgr *mgr, size_t size,
|
||||
ast_string_field *fields, int num_fields);
|
||||
|
||||
/*!
|
||||
\internal
|
||||
\brief Attempt to 'grow' an already allocated field to a larger size
|
||||
\param mgr Pointer to the pool manager structure
|
||||
\param needed Amount of space needed for this field
|
||||
\param fields Pointer to the first entry of the field array
|
||||
\param index Index position of the field within the structure
|
||||
\return 0 on success, non-zero on failure
|
||||
|
||||
This function will attempt to increase the amount of space allocated to
|
||||
an existing field to the amount requested; this is only possible if the
|
||||
field was the last field allocated from the current storage pool and
|
||||
the pool has enough space available. If so, the additional space will be
|
||||
allocated to this field and the field's address will not be changed.
|
||||
*/
|
||||
int __ast_string_field_index_grow(struct ast_string_field_mgr *mgr, size_t needed,
|
||||
ast_string_field *fields, int index);
|
||||
|
||||
/*!
|
||||
\internal
|
||||
\brief Allocate space for a field
|
||||
@@ -180,8 +199,8 @@ void __ast_string_field_index_build(struct ast_string_field_mgr *mgr,
|
||||
\return nothing
|
||||
*/
|
||||
void __ast_string_field_index_build_va(struct ast_string_field_mgr *mgr,
|
||||
ast_string_field *fields, int num_fields,
|
||||
int index, const char *format, va_list a1, va_list a2);
|
||||
ast_string_field *fields, int num_fields,
|
||||
int index, const char *format, va_list a1, va_list a2);
|
||||
|
||||
/*!
|
||||
\brief Declare a string field
|
||||
@@ -234,36 +253,36 @@ void __ast_string_field_index_build_va(struct ast_string_field_mgr *mgr,
|
||||
\return nothing
|
||||
*/
|
||||
#define ast_string_field_index_set(x, index, data) do { \
|
||||
char *__zz__ = (char*)(x)->__begin_field[index]; \
|
||||
size_t __dlen__ = strlen(data); \
|
||||
if( __dlen__ == 0 ) { (x)->__begin_field[index] = __ast_string_field_empty; \
|
||||
char *__zz__ = (char*) (x)->__begin_field[index]; \
|
||||
size_t __dlen__ = strlen(data) + 1; \
|
||||
if ( __dlen__ == 1 ) {\
|
||||
(x)->__begin_field[index] = __ast_string_field_empty; \
|
||||
} else { \
|
||||
if( __zz__[0] != 0 && __dlen__ <= strlen(__zz__) ) { \
|
||||
strcpy(__zz__, data); \
|
||||
} else { \
|
||||
if (((x)->__begin_field[index] = __ast_string_field_alloc_space(&(x)->__field_mgr, __dlen__ + 1, &(x)->__begin_field[0], ast_string_field_count(x)))) \
|
||||
strcpy((char*)(x)->__begin_field[index], data); \
|
||||
} \
|
||||
} \
|
||||
if (!__ast_string_field_index_grow(&(x)->__field_mgr, __dlen__, &(x)->__begin_field[0], index)) { \
|
||||
memcpy(__zz__, data, __dlen__); \
|
||||
} else { \
|
||||
if (((x)->__begin_field[index] = __ast_string_field_alloc_space(&(x)->__field_mgr, __dlen__, &(x)->__begin_field[0], ast_string_field_count(x)))) \
|
||||
memcpy((char*) (x)->__begin_field[index], data, __dlen__); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef FOR_TEST
|
||||
#define ast_string_field_index_logset(x, index, data, logstr) do { \
|
||||
char *__zz__ = (char*)(x)->__begin_field[index]; \
|
||||
size_t __dlen__ = strlen(data); \
|
||||
if( __dlen__ == 0 ) { (x)->__begin_field[index] = __ast_string_field_empty; \
|
||||
char *__zz__ = (char*) (x)->__begin_field[index]; \
|
||||
size_t __dlen__ = strlen(data) + 1; \
|
||||
if ( __dlen__ == 1 ) {\
|
||||
(x)->__begin_field[index] = __ast_string_field_empty; \
|
||||
} else { \
|
||||
if( __zz__[0] != 0 && __dlen__ <= strlen(__zz__) ) { \
|
||||
ast_verbose("%s: ======replacing '%s' with '%s'\n", logstr, __zz__, data); \
|
||||
strcpy(__zz__, data); \
|
||||
} else { \
|
||||
ast_verbose("%s: ++++++allocating room for '%s' to replace '%s'\n", logstr, data, __zz__); \
|
||||
if (((x)->__begin_field[index] = __ast_string_field_alloc_space(&(x)->__field_mgr, __dlen__ + 1, &(x)->__begin_field[0], ast_string_field_count(x)))) \
|
||||
strcpy((char*)(x)->__begin_field[index], data); \
|
||||
} \
|
||||
} \
|
||||
if (!__ast_string_field_index_grow(&(x)->__field_mgr, __dlen__, &(x)->__begin_field[0], index)) { \
|
||||
ast_verbose("%s: ======replacing '%s' with '%s'\n", logstr, __zz__, data); \
|
||||
memcpy(__zz__, data, __dlen__); \
|
||||
} else { \
|
||||
if (((x)->__begin_field[index] = __ast_string_field_alloc_space(&(x)->__field_mgr, __dlen__, &(x)->__begin_field[0], ast_string_field_count(x)))) \
|
||||
ast_verbose("%s: ++++++allocating room for '%s' to replace '%s'\n", logstr, data, __zz__); \
|
||||
memcpy((char*) (x)->__begin_field[index], data, __dlen__); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\brief Set a field to a simple string value
|
||||
@@ -275,10 +294,8 @@ void __ast_string_field_index_build_va(struct ast_string_field_mgr *mgr,
|
||||
#define ast_string_field_set(x, field, data) \
|
||||
ast_string_field_index_set(x, ast_string_field_index(x, field), data)
|
||||
|
||||
#ifdef FOR_TEST
|
||||
#define ast_string_field_logset(x, field, data, logstr) \
|
||||
ast_string_field_index_logset(x, ast_string_field_index(x, field), data, logstr)
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\brief Set a field to a complex (built) value
|
||||
|
30
main/utils.c
30
main/utils.c
@@ -1223,6 +1223,7 @@ static int add_string_pool(struct ast_string_field_mgr *mgr, size_t size)
|
||||
mgr->size = size;
|
||||
mgr->space = size;
|
||||
mgr->used = 0;
|
||||
mgr->last_alloc = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1259,12 +1260,36 @@ ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr
|
||||
result = mgr->pool->base + mgr->used;
|
||||
mgr->used += needed;
|
||||
mgr->space -= needed;
|
||||
mgr->last_alloc = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
int __ast_string_field_index_grow(struct ast_string_field_mgr *mgr, size_t needed,
|
||||
ast_string_field *fields, int index)
|
||||
{
|
||||
int grow = needed - (strlen(fields[index]) + 1);
|
||||
|
||||
if (grow <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fields[index] != mgr->last_alloc) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mgr->space < grow) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
mgr->space -= grow;
|
||||
mgr->used += grow;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __ast_string_field_index_build_va(struct ast_string_field_mgr *mgr,
|
||||
ast_string_field *fields, int num_fields,
|
||||
int index, const char *format, va_list ap1, va_list ap2)
|
||||
ast_string_field *fields, int num_fields,
|
||||
int index, const char *format, va_list ap1, va_list ap2)
|
||||
{
|
||||
size_t needed;
|
||||
|
||||
@@ -1285,6 +1310,7 @@ void __ast_string_field_index_build_va(struct ast_string_field_mgr *mgr,
|
||||
}
|
||||
|
||||
fields[index] = mgr->pool->base + mgr->used;
|
||||
mgr->last_alloc = fields[index];
|
||||
mgr->used += needed;
|
||||
mgr->space -= needed;
|
||||
}
|
||||
|
Reference in New Issue
Block a user