[svn-commits] mjordan: branch mjordan/12-memorypool r402913 - in /team/mjordan/12-memorypoo...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Nov 20 10:45:51 CST 2013


Author: mjordan
Date: Wed Nov 20 10:45:48 2013
New Revision: 402913

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=402913
Log:
Create branch

Added:
    team/mjordan/12-memorypool/
      - copied from r402912, branches/12/
Modified:
    team/mjordan/12-memorypool/include/asterisk/astobj2.h
    team/mjordan/12-memorypool/include/asterisk/channel.h
    team/mjordan/12-memorypool/include/asterisk/channel_internal.h
    team/mjordan/12-memorypool/main/astobj2.c
    team/mjordan/12-memorypool/main/channel.c
    team/mjordan/12-memorypool/main/channel_internal_api.c
    team/mjordan/12-memorypool/main/stasis_channels.c

Modified: team/mjordan/12-memorypool/include/asterisk/astobj2.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-memorypool/include/asterisk/astobj2.h?view=diff&rev=402913&r1=402912&r2=402913
==============================================================================
--- team/mjordan/12-memorypool/include/asterisk/astobj2.h (original)
+++ team/mjordan/12-memorypool/include/asterisk/astobj2.h Wed Nov 20 10:45:48 2013
@@ -407,6 +407,8 @@
 	AO2_ALLOC_OPT_LOCK_NOLOCK = (2 << 0),
 	/*! The ao2 object locking option field mask. */
 	AO2_ALLOC_OPT_LOCK_MASK = (3 << 0),
+    /*! The ao2 object is part of a memory pool. */
+    AO2_ALLOC_OPT_MEMORY_POOL_ITEM = (4 << 0),
 };
 
 /*!
@@ -1933,4 +1935,76 @@
 #endif
 void ao2_iterator_cleanup(struct ao2_iterator *iter);
 
+/*!
+ * \brief Construction function for memory pool items
+ *
+ * \param newobj The new object being built
+ *
+ * This function is called one time on each item in a memory pool. It should be
+ * used to create objects in an item that only need to be performed once, such
+ * as string fields.
+ *
+ * \retval 0 on success
+ * \retval any other value on error
+ */
+typedef int (*ao2_constructor_fn)(void *newobj);
+
+/*!
+ * \brief Cleanup function for memory pool items
+ *
+ * \param obj The object being cleaned up
+ *
+ * This function is called when the reference count on an item in the pool
+ * reaches 0. The memory comprising the item is not reclaimed, but references
+ * that the item holds should be released.
+ */
+typedef void (*ao2_cleanup_fn)(void *obj);
+
+struct ao2_memory_pool;
+
+
+/*!
+ * \brief Allocate a memory pool
+ *
+ */
+#if defined(REF_DEBUG) || defined(__AST_DEBUG_MALLOC)
+
+#define ao2_t_memory_pool_alloc(pool_size, obj_size, ctor_fn, cleanup_fn, dtor_fn, tag) __ao2_memory_pool_alloc_debug((pool_size), (obj_size), (ctor_fn), (cleanup_fn), (dtor_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_memory_pool_alloc(pool_size, obj_size, ctor_fn, cleanup_fn, dtor_fn) __ao2_memory_pool_alloc_debug((pool_size), (obj_size), (ctor_fn), (cleanup_fn), (dtor_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+#else
+
+#define ao2_t_memory_pool_alloc(pool_size, obj_size, ctor_fn, cleanup_fn, dtor_fn, tag) __ao2_memory_pool_alloc((pool_size), (obj_size), (ctor_fn), (cleanup_fn), (dtor_fn))
+#define ao2_memory_pool_alloc(pool_size, obj_size, ctor_fn, cleanup_fn, dtor_fn) __ao2_memory_pool_alloc((pool_size), (obj_size), (ctor_fn), (cleanup_fn), (dtor_fn))
+
+#endif
+
+struct ao2_memory_pool *__ao2_memory_pool_alloc_debug(size_t pool_size, size_t obj_size,
+	ao2_constructor_fn ctor_fn, ao2_cleanup_fn cleanup_fn, ao2_destructor_fn dtor_fn,
+	const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
+struct ao2_memory_pool *__ao2_memory_pool_alloc(size_t pool_size, size_t obj_size,
+	ao2_constructor_fn ctor_fn, ao2_cleanup_fn cleanup_fn, ao2_destructor_fn dtor_fn) attribute_warn_unused_result;
+
+/*!
+ * \brief Request an item from the memory pool
+ *
+ * NOTE:
+ */
+
+#if defined(REF_DEBUG) || defined(__AST_DEBUG_MALLOC)
+
+#define ao2_t_memory_pool_request(pool, tag) __ao2_memory_pool_request_debug((pool), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_memory_pool_request(pool) __ao2_memory_pool_request_debug((pool), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+#else
+
+#define ao2_t_memory_pool_request(pool, tag) __ao2_memory_pool_request((pool))
+#define ao2_memory_pool_request(pool) __ao2_memory_pool_request((pool))
+
+#endif
+
+void *__ao2_memory_pool_request_debug(struct ao2_memory_pool *pool, const char *tag,
+	const char *file, int line, const char *func) attribute_warn_unused_result;
+void *__ao2_memory_pool_request(struct ao2_memory_pool *pool) attribute_warn_unused_result;
+
 #endif /* _ASTERISK_ASTOBJ2_H */

Modified: team/mjordan/12-memorypool/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-memorypool/include/asterisk/channel.h?view=diff&rev=402913&r1=402912&r2=402913
==============================================================================
--- team/mjordan/12-memorypool/include/asterisk/channel.h (original)
+++ team/mjordan/12-memorypool/include/asterisk/channel.h Wed Nov 20 10:45:48 2013
@@ -4048,6 +4048,8 @@
 struct ast_channel *ast_channel_internal_bridged_channel(const struct ast_channel *chan);
 void ast_channel_internal_bridged_channel_set(struct ast_channel *chan, struct ast_channel *value);
 
+struct ao2_memory_pool *ast_channel_snapshot_pool(struct ast_channel *chan);
+
 /*!
  * \since 11
  * \brief Retreive a comma-separated list of channels for which dialed cause information is available

Modified: team/mjordan/12-memorypool/include/asterisk/channel_internal.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-memorypool/include/asterisk/channel_internal.h?view=diff&rev=402913&r1=402912&r2=402913
==============================================================================
--- team/mjordan/12-memorypool/include/asterisk/channel_internal.h (original)
+++ team/mjordan/12-memorypool/include/asterisk/channel_internal.h Wed Nov 20 10:45:48 2013
@@ -24,4 +24,4 @@
 int ast_channel_internal_is_finalized(struct ast_channel *chan);
 void ast_channel_internal_cleanup(struct ast_channel *chan);
 int ast_channel_internal_setup_topics(struct ast_channel *chan);
-
+int ast_channel_internal_setup_memory_pool(struct ast_channel *chan);

Modified: team/mjordan/12-memorypool/main/astobj2.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-memorypool/main/astobj2.c?view=diff&rev=402913&r1=402912&r2=402913
==============================================================================
--- team/mjordan/12-memorypool/main/astobj2.c (original)
+++ team/mjordan/12-memorypool/main/astobj2.c Wed Nov 20 10:45:48 2013
@@ -51,6 +51,9 @@
  */
 struct __priv_data {
 	int ref_counter;
+	/*! Function called by memory pools when object is reclaimed by pool */
+	ao2_cleanup_fn cleanup_fn;
+	/*! Function called when object is destroyed */
 	ao2_destructor_fn destructor_fn;
 	/*! User data size for stats */
 	size_t data_size;
@@ -142,6 +145,9 @@
 
 #define INTERNAL_OBJ_RWLOCK(user_data) \
 	((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock)))
+
+#define INTERNAL_OBJ_MEMORY_POOL(user_data) \
+	(struct ao2_memory_pool_item *) (((char *) (user_data)) - sizeof(struct ao2_memory_pool_item))
 
 /*!
  * \brief convert from a pointer _p to a user-defined object
@@ -431,6 +437,46 @@
 	return NULL;
 }
 
+/*! \brief An item in a memory pool */
+struct ao2_memory_pool_item {
+	/*! Pointer to the next free item in the pool. When this item is removed
+	 * from the pool, this pointer will be NULL. */
+	struct ao2_memory_pool_item *next;
+	/*! Pointer/reference to the pool. When the item is removed, the reference
+	 * to the pool is bumped. When not requested, this pointer should not be
+	 * used. */
+	struct ao2_memory_pool *pool;
+#if defined(REF_DEBUG) || defined(__AST_DEBUG_MALLOC)
+	/*! Debug information populated when this object is requested */
+	struct {
+		const char *tag;
+		const char *file;
+		const char *func;
+		int line;
+	} debug;
+#endif
+	/*! The actual ao2 object, with lock */
+	struct astobj2_lock ao2_obj;
+};
+
+/*! \brief A pool of ao2 objects */
+struct ao2_memory_pool {
+	/*! Constructor function for each item in the pool */
+	ao2_constructor_fn constructor_fn;
+	/*! Size (number of items) in the pool */
+	size_t pool_size;
+	/*! Size of the user data in each item in the pool */
+	size_t obj_size;
+	/*! A memory pool to be used if this one is exhausted. */
+	struct ao2_memory_pool *reserve_pool;
+	/*! Pointer to the next free item in the pool */
+	struct ao2_memory_pool_item *first_free_item;
+	/*! Pointer to the last free item in the pool */
+	struct ao2_memory_pool_item *last_free_item;
+	/*! The actual items in the memory pool */
+	struct ao2_memory_pool_item *items[0];
+};
+
 static int internal_ao2_ref(void *user_data, int delta, const char *file, int line, const char *func)
 {
 	struct astobj2 *obj = INTERNAL_OBJ(user_data);
@@ -469,8 +515,37 @@
 	}
 
 	/* last reference, destroy the object */
-	if (obj->priv_data.destructor_fn != NULL) {
+	if ((obj->priv_data.options & AO2_ALLOC_OPT_MEMORY_POOL_ITEM) == 0
+		&& obj->priv_data.destructor_fn != NULL) {
 		obj->priv_data.destructor_fn(user_data);
+	} else if (obj->priv_data.options & AO2_ALLOC_OPT_MEMORY_POOL_ITEM) {
+		struct ao2_memory_pool_item *item = INTERNAL_OBJ_MEMORY_POOL(user_data);
+
+		if (obj->priv_data.cleanup_fn) {
+			obj->priv_data.cleanup_fn(user_data);
+		}
+
+#if defined(REF_DEBUG) || defined(__AO2_DEBUG_MALLOC)
+		item->debug.tag = NULL;
+		item->debug.file = NULL;
+		item->debug.func = NULL;
+		item->debug.line = 0;
+#endif
+		ast_assert(item->next == NULL);
+		ao2_lock(item->pool);
+		if (item->pool->first_free_item == NULL) {
+			item->pool->first_free_item = item;
+		}
+
+		/* Insert the item at the end of the list */
+		if (item->pool->last_free_item) {
+			item->pool->last_free_item->next = item;
+		}
+		item->pool->last_free_item = item;
+		ao2_unlock(item->pool);
+		ao2_t_ref(item->pool, -1, "Remove pool ref from item");
+
+		return ret;
 	}
 
 #ifdef AO2_DEBUG
@@ -645,6 +720,232 @@
 	return internal_ao2_alloc(data_size, destructor_fn, options, __FILE__, __LINE__, __FUNCTION__);
 }
 
+/*! \brief Compute where in a memory pool an item exists, based on its index */
+#define MEMORY_POOL_ITEM(pool, index) \
+	((struct ao2_memory_pool_item *)((char *)((pool)->items) + (index) * ((pool)->obj_size + sizeof(struct ao2_memory_pool_item))))
+
+/*!
+ * \brief Destructor for a memory pool
+ *
+ * \param obj The memory pool to be destroyed
+ *
+ * This will destroy all items in the memory pool and release any reserved pools
+ * off of this pool. Note that this should never be called until all items in
+ * the memory pool are no longer referenced by consumers.
+ */
+static void memory_pool_dtor(void *obj)
+{
+	struct ao2_memory_pool *pool = obj;
+	int i;
+
+	for (i = 0; i < pool->pool_size; i++) {
+		struct ao2_memory_pool_item *item = MEMORY_POOL_ITEM(pool, i);
+		struct astobj2 *item_obj = (struct astobj2 *)&item->ao2_obj.priv_data;
+
+		if (item_obj->priv_data.destructor_fn) {
+			item_obj->priv_data.destructor_fn(&item->ao2_obj.user_data);
+		}
+
+		item_obj->priv_data.magic = 0;
+		ast_mutex_destroy(&item->ao2_obj.mutex.lock);
+	}
+
+	if (pool->reserve_pool) {
+		ao2_t_ref(pool->reserve_pool, -1, "Release reserve pool");
+	}
+}
+
+/*! \brief Compute the size of a memory pool */
+#define POOL_SIZE(pool, obj_size, pool_size) \
+	sizeof(*(pool)) + (sizeof(struct ao2_memory_pool_item) + (obj_size)) * (pool_size)
+
+/*!
+ * \internal
+ * \brief Initialize an allocated pool
+ *
+ * \param pool The pool to initialize
+ * \param pool_size The number of items in the pool
+ * \param obj_size The size of each item in the pool
+ * \param ctor_fn Constructor function for each item
+ * \param cleanup_fn Cleanup function for each item
+ * \param dtor_fn Destructor function for each item
+ *
+ * \retval The pool on success
+ * \retval NULL on error
+ */
+static struct ao2_memory_pool *internal_ao2_memory_pool_init(struct ao2_memory_pool *pool,
+	size_t pool_size, size_t obj_size, ao2_constructor_fn ctor_fn,
+	ao2_cleanup_fn cleanup_fn, ao2_destructor_fn dtor_fn)
+{
+	struct ao2_memory_pool_item *prev = NULL;
+	int i;
+
+	pool->constructor_fn = ctor_fn;
+	pool->pool_size = pool_size;
+	pool->obj_size = obj_size;
+
+	/* Initialize each object in the pool */
+	for (i = 0; i < pool->pool_size; i++) {
+		struct ao2_memory_pool_item *item = MEMORY_POOL_ITEM(pool, i);
+
+		ast_mutex_init(&item->ao2_obj.mutex.lock);
+
+		item->ao2_obj.priv_data.ref_counter = 0;
+		item->ao2_obj.priv_data.cleanup_fn = cleanup_fn;
+		item->ao2_obj.priv_data.destructor_fn = dtor_fn;
+		item->ao2_obj.priv_data.data_size = pool->obj_size;
+		item->ao2_obj.priv_data.options = AO2_ALLOC_OPT_MEMORY_POOL_ITEM | AO2_ALLOC_OPT_LOCK_MUTEX;
+		item->ao2_obj.priv_data.magic = AO2_MAGIC;
+		if (pool->constructor_fn && pool->constructor_fn(item->ao2_obj.user_data)) {
+			ao2_t_ref(pool, -1, "Dispose of pool due to item init failure");
+			return NULL;
+		}
+
+		item->pool = pool;
+		if (prev) {
+			prev->next = item;
+		}
+		prev = item;
+	}
+
+	pool->first_free_item = MEMORY_POOL_ITEM(pool, 0);
+	pool->last_free_item = MEMORY_POOL_ITEM(pool, (pool->pool_size - 1));
+	return pool;
+}
+
+struct ao2_memory_pool *__ao2_memory_pool_alloc_debug(size_t pool_size, size_t obj_size,
+	ao2_constructor_fn ctor_fn, ao2_cleanup_fn cleanup_fn, ao2_destructor_fn dtor_fn,
+	const char *tag, const char *file, int line, const char *func)
+{
+	struct ao2_memory_pool *pool;
+
+#if defined(REF_DEBUG)
+	pool = __ao2_alloc_debug(POOL_SIZE(pool, obj_size, pool_size),
+							   memory_pool_dtor,
+							   AO2_ALLOC_OPT_LOCK_MUTEX,
+							   tag, file, line, func, 1);
+#elif defined(__AST_DEBUG_MALLOC)
+	pool = __ao2_alloc_debug(POOL_SIZE(pool, obj_size, pool_size),
+							   memory_pool_dtor,
+							   AO2_ALLOC_OPT_LOCK_MUTEX,
+							   tag, file, line, func, 0);
+#else
+	/* We shouldn't get here if not compiled with a debug mode */
+	pool = NULL;
+	ast_assert(0);
+#endif
+	if (!pool) {
+		return NULL;
+	}
+
+	return internal_ao2_memory_pool_init(pool, pool_size, obj_size, ctor_fn,
+		cleanup_fn, dtor_fn);
+}
+
+struct ao2_memory_pool *__ao2_memory_pool_alloc(size_t pool_size, size_t obj_size,
+    ao2_constructor_fn ctor_fn, ao2_cleanup_fn cleanup_fn, ao2_destructor_fn dtor_fn)
+{
+	struct ao2_memory_pool *pool;
+
+	pool = __ao2_alloc(POOL_SIZE(pool, obj_size, pool_size),
+					   memory_pool_dtor,
+					   AO2_ALLOC_OPT_LOCK_MUTEX);
+	if (!pool) {
+		return NULL;
+	}
+
+	return internal_ao2_memory_pool_init(pool, pool_size, obj_size, ctor_fn,
+		cleanup_fn, dtor_fn);
+}
+
+static void *internal_ao2_memory_pool_request(struct ao2_memory_pool *pool)
+{
+	struct ao2_memory_pool_item *item;
+
+	item = pool->first_free_item;
+	item->ao2_obj.priv_data.ref_counter = 1;
+	ao2_t_ref(item->pool, +1, "Increase pool ref count from item request");
+
+	/* Set up the next item in the pool and remove ourselves from it */
+	pool->first_free_item = item->next;
+	if (pool->last_free_item == item) {
+		pool->last_free_item = NULL;
+	}
+	item->next = NULL;
+
+	return EXTERNAL_OBJ(&item->ao2_obj);
+}
+
+void *__ao2_memory_pool_request_debug(struct ao2_memory_pool *pool, const char *tag,
+	const char *file, int line, const char *func)
+{
+#if defined(REF_DEBUG)
+	int refo;
+#endif
+#if defined(REF_DEBUG) || defined(__AST_DEBUG_MALLOC)
+	struct ao2_memory_pool_item *item;
+#endif
+	void *user_data;
+
+	if (!pool) {
+		return NULL;
+	}
+
+	if (pool->first_free_item == NULL) {
+		if (!pool->reserve_pool) {
+			pool->reserve_pool = __ao2_memory_pool_alloc_debug(pool->pool_size * 2,
+				pool->obj_size,
+				pool->constructor_fn,
+				MEMORY_POOL_ITEM(pool, 0)->ao2_obj.priv_data.cleanup_fn,
+				MEMORY_POOL_ITEM(pool, 0)->ao2_obj.priv_data.destructor_fn,
+				tag, file, line, func);
+			if (!pool->reserve_pool) {
+				return NULL;
+			}
+		}
+		return __ao2_memory_pool_request_debug(pool->reserve_pool, tag, file, line, func);
+	}
+
+	user_data = internal_ao2_memory_pool_request(pool);
+#if defined(REF_DEBUG) || defined(__AST_DEBUG_MALLOC)
+	item = INTERNAL_OBJ_MEMORY_POOL(user_data);
+	item->debug.tag = tag;
+	item->debug.file = file;
+	item->debug.func = func;
+	item->debug.line = line;
+#endif
+#if defined(REF_DEBUG)
+	if ((refo = fopen(REF_FILE, "a"))) {
+		fprintf(refo, "%p =1   %s:%d:%s (%s)\n", item, file, line, func, tag);
+		fclose(refo);
+	}
+#endif
+
+	return user_data;	
+}
+
+void *__ao2_memory_pool_request(struct ao2_memory_pool *pool)
+{
+	if (!pool) {
+		return NULL;
+	}
+
+	if (pool->first_free_item == NULL) {
+		if (!pool->reserve_pool) {
+			pool->reserve_pool = ao2_memory_pool_alloc(pool->pool_size * 2,
+				pool->obj_size,
+				pool->constructor_fn,
+				MEMORY_POOL_ITEM(pool, 0)->ao2_obj.priv_data.cleanup_fn,
+				MEMORY_POOL_ITEM(pool, 0)->ao2_obj.priv_data.destructor_fn);
+			if (!pool->reserve_pool) {
+				return NULL;
+			}
+		}
+		return __ao2_memory_pool_request(pool->reserve_pool);
+	}
+
+	return internal_ao2_memory_pool_request(pool);
+}
 
 void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name)
 {

Modified: team/mjordan/12-memorypool/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-memorypool/main/channel.c?view=diff&rev=402913&r1=402912&r2=402913
==============================================================================
--- team/mjordan/12-memorypool/main/channel.c (original)
+++ team/mjordan/12-memorypool/main/channel.c Wed Nov 20 10:45:48 2013
@@ -874,6 +874,10 @@
 
 	if (!(tmp = ast_channel_internal_alloc(ast_channel_destructor, linkedid))) {
 		/* Channel structure allocation failure. */
+		return NULL;
+	}
+	if (ast_channel_internal_setup_memory_pool(tmp)) {
+		ao2_ref(tmp, -1);
 		return NULL;
 	}
 

Modified: team/mjordan/12-memorypool/main/channel_internal_api.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-memorypool/main/channel_internal_api.c?view=diff&rev=402913&r1=402912&r2=402913
==============================================================================
--- team/mjordan/12-memorypool/main/channel_internal_api.c (original)
+++ team/mjordan/12-memorypool/main/channel_internal_api.c Wed Nov 20 10:45:48 2013
@@ -208,6 +208,7 @@
 	struct timeval sending_dtmf_tv;		/*!< The time this channel started sending the current digit. (Invalid if sending_dtmf_digit is zero.) */
 	struct stasis_cp_single *topics;		/*!< Topic for all channel's events */
 	struct stasis_forward *endpoint_forward;	/*!< Subscription for event forwarding to endpoint's topic */
+	struct ao2_memory_pool *snapshot_pool;	/*!< Pool of snapshots */
 };
 
 /*! \brief The monotonically increasing integer counter for channel uniqueids */
@@ -1313,6 +1314,11 @@
 	return &chan->flags;
 }
 
+struct ao2_memory_pool *ast_channel_snapshot_pool(struct ast_channel *chan)
+{
+	return chan->snapshot_pool;
+}
+
 static int collect_names_cb(void *obj, void *arg, int flags) {
 	struct ast_control_pvt_cause_code *cause_code = obj;
 	struct ast_str **str = arg;
@@ -1378,6 +1384,39 @@
 }
 
 #define DIALED_CAUSES_BUCKETS 37
+
+static void channel_snapshot_cleanup(void *obj)
+{
+	struct ast_channel_snapshot *snapshot = obj;
+
+	ao2_cleanup(snapshot->manager_vars);
+	snapshot->manager_vars = NULL;
+	ao2_cleanup(snapshot->channel_vars);	
+	snapshot->channel_vars = NULL;
+}
+
+static void channel_snapshot_dtor(void *obj)
+{
+	struct ast_channel_snapshot *snapshot = obj;
+
+	ast_string_field_free_memory(snapshot);	
+}
+
+static int channel_snapshot_ctor(void *obj)
+{
+	struct ast_channel_snapshot *snapshot = obj;
+
+	return ast_string_field_init(snapshot, 1024);
+}
+
+int ast_channel_internal_setup_memory_pool(struct ast_channel *chan)
+{
+	if (!(chan->snapshot_pool = ao2_memory_pool_alloc(16, sizeof(struct ast_channel_snapshot),
+		channel_snapshot_ctor, channel_snapshot_cleanup, channel_snapshot_dtor))) {
+		return -1;
+	}
+	return 0;
+}
 
 struct ast_channel *__ast_channel_internal_alloc(void (*destructor)(void *obj), const char *linkedid, const char *file, int line, const char *function)
 {
@@ -1425,6 +1464,12 @@
 		chan->dialed_causes = NULL;
 	}
 
+	if (chan->snapshot_pool) {
+		ao2_t_ref(chan->snapshot_pool, -1,
+			"Dispose of pool during channel destruction");
+		chan->snapshot_pool = NULL;
+	}
+
 	ast_string_field_free_memory(chan);
 
 	chan->endpoint_forward = stasis_forward_cancel(chan->endpoint_forward);

Modified: team/mjordan/12-memorypool/main/stasis_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-memorypool/main/stasis_channels.c?view=diff&rev=402913&r1=402912&r2=402913
==============================================================================
--- team/mjordan/12-memorypool/main/stasis_channels.c (original)
+++ team/mjordan/12-memorypool/main/stasis_channels.c Wed Nov 20 10:45:48 2013
@@ -161,18 +161,9 @@
 	return strcasecmp(left->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
 }
 
-static void channel_snapshot_dtor(void *obj)
-{
-	struct ast_channel_snapshot *snapshot = obj;
-
-	ast_string_field_free_memory(snapshot);
-	ao2_cleanup(snapshot->manager_vars);
-	ao2_cleanup(snapshot->channel_vars);
-}
-
 struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan)
 {
-	RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
+	struct ast_channel_snapshot *snapshot;
 	RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
 	char nativeformats[256];
 	struct ast_str *write_transpath = ast_str_alloca(256);
@@ -185,8 +176,10 @@
 		return NULL;
 	}
 
-	snapshot = ao2_alloc(sizeof(*snapshot), channel_snapshot_dtor);
-	if (!snapshot || ast_string_field_init(snapshot, 1024)) {
+	ao2_lock(ast_channel_snapshot_pool(chan));
+	snapshot = ao2_memory_pool_request(ast_channel_snapshot_pool(chan));
+	ao2_unlock(ast_channel_snapshot_pool(chan));
+	if (!snapshot) {
 		return NULL;
 	}
 
@@ -267,7 +260,6 @@
 	snapshot->channel_vars = ast_channel_get_vars(chan);
 	snapshot->tech_properties = ast_channel_tech(chan)->properties;
 
-	ao2_ref(snapshot, +1);
 	return snapshot;
 }
 




More information about the svn-commits mailing list