Merged revisions 132872 via svnmerge from
authorKevin P. Fleming <kpfleming@digium.com>
Wed, 23 Jul 2008 16:30:18 +0000 (16:30 +0000)
committerKevin P. Fleming <kpfleming@digium.com>
Wed, 23 Jul 2008 16:30:18 +0000 (16:30 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r132872 | kpfleming | 2008-07-23 06:52:18 -0500 (Wed, 23 Jul 2008) | 2 lines

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/trunk@132964 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/stringfields.h
main/utils.c

index 65f1b53..b0cda69 100644 (file)
@@ -135,12 +135,30 @@ struct ast_string_field_pool {
   pool, so the numbers here reflect just that.
 */
 struct ast_string_field_mgr {
-       size_t size;            /*!< the total size of the current pool */
-       size_t used;            /*!< the space used in the current pool */
+       size_t size;                            /*!< the total size of the current pool */
+       size_t used;                            /*!< the space used in the current pool */
+       ast_string_field last_alloc;            /*!< the last field allocated */
 };
 
 /*!
   \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 ptr Pointer to a 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_ptr_grow(struct ast_string_field_mgr *mgr, size_t needed,
+                               const ast_string_field *ptr);
+
+/*!
+  \internal
   \brief Allocate space for a field
   \param mgr Pointer to the pool manager structure
   \param needed Amount of space needed for this field
@@ -152,7 +170,7 @@ struct ast_string_field_mgr {
   an additional pool will be allocated.
 */
 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr,
-        struct ast_string_field_pool **pool_head, size_t needed);
+                                               struct ast_string_field_pool **pool_head, size_t needed);
 
 /*!
   \internal
@@ -164,8 +182,8 @@ ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr
   \return nothing
 */
 void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
-       struct ast_string_field_pool **pool_head,
-       const ast_string_field *ptr, const char *format, ...);
+                                 struct ast_string_field_pool **pool_head,
+                                 const ast_string_field *ptr, const char *format, ...);
 
 /*!
   \internal
@@ -179,8 +197,8 @@ void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
   \return nothing
 */
 void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
-       struct ast_string_field_pool **pool_head,
-       const ast_string_field *ptr, const char *format, va_list a1, va_list a2);
+                                    struct ast_string_field_pool **pool_head,
+                                    const ast_string_field *ptr, const char *format, va_list a1, va_list a2);
 
 /*!
   \brief Declare a string field
@@ -233,17 +251,16 @@ int __ast_string_field_init(struct ast_string_field_mgr *mgr,
   \param data String value to be copied into the field
   \return nothing
 */
-
 #define ast_string_field_ptr_set(x, ptr, data) do {            \
        const char *__d__ = (data);                             \
-       size_t __dlen__ = (__d__) ? strlen(__d__) : 0;          \
-       const char **__p__ = (const char **)(ptr);              \
-       if (__dlen__ == 0)                                      \
+       size_t __dlen__ = (__d__) ? strlen(__d__) + 1 : 1;      \
+       const char **__p__ = (const char **) (ptr);             \
+       if (__dlen__ == 1)                                      \
                *__p__ = __ast_string_field_empty;              \
-       else if (__dlen__ <= strlen(*__p__))                    \
-               strcpy((char *)*__p__, __d__);                  \
-       else if ( (*__p__ = __ast_string_field_alloc_space(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__ + 1) ) ) \
-               strcpy((char *)*__p__, __d__);                  \
+       else if (!__ast_string_field_ptr_grow(&(x)->__field_mgr, __dlen__, ptr)) \
+               memcpy((char *) *__p__, __d__, __dlen__);       \
+       else if ((*__p__ = __ast_string_field_alloc_space(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__))) \
+               memcpy((char *) *__p__, __d__, __dlen__);       \
        } while (0)
 
 /*!
@@ -253,11 +270,10 @@ int __ast_string_field_init(struct ast_string_field_mgr *mgr,
   \param data String value to be copied into the field
   \return nothing
 */
-#define ast_string_field_set(x, field, data)   do {            \
+#define ast_string_field_set(x, field, data) do {              \
        ast_string_field_ptr_set(x, &(x)->field, data);         \
        } while (0)
 
-
 /*!
   \brief Set a field to a complex (built) value
   \param x Pointer to a structure containing fields
index f156770..eff270f 100644 (file)
@@ -1425,7 +1425,8 @@ const char __ast_string_field_empty[] = ""; /*!< the empty string */
  * fields in *mgr reflect the size of that only.
  */
 static int add_string_pool(struct ast_string_field_mgr *mgr,
-       struct ast_string_field_pool **pool_head, size_t size)
+                          struct ast_string_field_pool **pool_head,
+                          size_t size)
 {
        struct ast_string_field_pool *pool;
 
@@ -1436,6 +1437,7 @@ static int add_string_pool(struct ast_string_field_mgr *mgr,
        *pool_head = pool;
        mgr->size = size;
        mgr->used = 0;
+       mgr->last_alloc = NULL;
 
        return 0;
 }
@@ -1451,14 +1453,16 @@ static int add_string_pool(struct ast_string_field_mgr *mgr,
  *     This must be done before destroying the object.
  */
 int __ast_string_field_init(struct ast_string_field_mgr *mgr,
-       struct ast_string_field_pool **pool_head, int size)
+                           struct ast_string_field_pool **pool_head,
+                           int size)
 {
-       const char **p = (const char **)pool_head + 1;
+       const char **p = (const char **) pool_head + 1;
        struct ast_string_field_pool *cur = *pool_head;
 
        /* clear fields - this is always necessary */
-       while ((struct ast_string_field_mgr *)p != mgr)
+       while ((struct ast_string_field_mgr *) p != mgr)
                *p++ = __ast_string_field_empty;
+       mgr->last_alloc = NULL;
        if (size > 0) {                 /* allocate the initial pool */
                *pool_head = NULL;
                return add_string_pool(mgr, pool_head, size);
@@ -1474,16 +1478,19 @@ int __ast_string_field_init(struct ast_string_field_mgr *mgr,
                (*pool_head)->prev = NULL;
                mgr->used = 0;
        }
+
        while (cur) {
                struct ast_string_field_pool *prev = cur->prev;
+
                ast_free(cur);
                cur = prev;
        }
+
        return 0;
 }
 
 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr,
-       struct ast_string_field_pool **pool_head, size_t needed)
+                                               struct ast_string_field_pool **pool_head, size_t needed)
 {
        char *result = NULL;
        size_t space = mgr->size - mgr->used;
@@ -1500,17 +1507,41 @@ ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr
 
        result = (*pool_head)->base + mgr->used;
        mgr->used += needed;
+       mgr->last_alloc = result;
        return result;
 }
 
+int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr, size_t needed,
+                               const ast_string_field *ptr)
+{
+       int grow = needed - (strlen(*ptr) + 1);
+       size_t space = mgr->size - mgr->used;
+
+       if (grow <= 0) {
+               return 0;
+       }
+
+       if (*ptr != mgr->last_alloc) {
+               return 1;
+       }
+
+       if (space < grow) {
+               return 1;
+       }
+
+       mgr->used += grow;
+
+       return 0;
+}
+
 __attribute((format (printf, 4, 0)))
 void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
-       struct ast_string_field_pool **pool_head,
-       const ast_string_field *ptr, const char *format, va_list ap1, va_list ap2)
+                                    struct ast_string_field_pool **pool_head,
+                                    const ast_string_field *ptr, const char *format, va_list ap1, va_list ap2)
 {
        size_t needed;
        char *dst = (*pool_head)->base + mgr->used;
-       const char **p = (const char **)ptr;
+       const char **p = (const char **) ptr;
        size_t space = mgr->size - mgr->used;
 
        /* try to write using available space */
@@ -1531,14 +1562,14 @@ void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
                vsprintf(dst, format, ap2);
        }
 
-       *p = dst;
+       mgr->last_alloc = *p = dst;
        mgr->used += needed;
 }
 
 __attribute((format (printf, 4, 5)))
 void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
-       struct ast_string_field_pool **pool_head,
-       const ast_string_field *ptr, const char *format, ...)
+                                 struct ast_string_field_pool **pool_head,
+                                 const ast_string_field *ptr, const char *format, ...)
 {
        va_list ap1, ap2;