[asterisk-commits] rmudgett: branch rmudgett/ao2_enhancements r360762 - /team/rmudgett/ao2_enhan...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Mar 28 22:48:07 CDT 2012
Author: rmudgett
Date: Wed Mar 28 22:48:03 2012
New Revision: 360762
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=360762
Log:
Collect all hash container specific code into one section of the file.
Modified:
team/rmudgett/ao2_enhancements/main/astobj2.c
Modified: team/rmudgett/ao2_enhancements/main/astobj2.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/ao2_enhancements/main/astobj2.c?view=diff&rev=360762&r1=360761&r2=360762
==============================================================================
--- team/rmudgett/ao2_enhancements/main/astobj2.c (original)
+++ team/rmudgett/ao2_enhancements/main/astobj2.c Wed Mar 28 22:48:03 2012
@@ -870,6 +870,371 @@
};
/*!
+ * return the number of elements in the container
+ */
+int ao2_container_count(struct ao2_container *c)
+{
+ return c->elements;
+}
+
+int __ao2_link_debug(struct ao2_container *c, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func)
+{
+ if (!INTERNAL_OBJ(obj_new) || !INTERNAL_OBJ(c) || !c->v_table || !c->v_table->link) {
+ /* Sanity checks. */
+ return 0;
+ }
+ return c->v_table->link(c, obj_new, flags, tag, file, line, func);
+}
+
+int __ao2_link(struct ao2_container *c, void *obj_new, int flags)
+{
+ if (!INTERNAL_OBJ(obj_new) || !INTERNAL_OBJ(c) || !c->v_table || !c->v_table->link) {
+ /* Sanity checks. */
+ return 0;
+ }
+ return c->v_table->link(c, obj_new, flags, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
+}
+
+/*!
+ * \brief another convenience function is a callback that matches on address
+ */
+int ao2_match_by_addr(void *user_data, void *arg, int flags)
+{
+ return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
+}
+
+/*
+ * Unlink an object from the container
+ * and destroy the associated * bucket_entry structure.
+ */
+void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, int flags,
+ const char *tag, const char *file, int line, const char *func)
+{
+ if (!INTERNAL_OBJ(user_data)) {
+ /* Sanity checks. */
+ return NULL;
+ }
+
+ flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
+ __ao2_callback_debug(c, flags, ao2_match_by_addr, user_data, tag, file, line, func);
+
+ return NULL;
+}
+
+void *__ao2_unlink(struct ao2_container *c, void *user_data, int flags)
+{
+ if (!INTERNAL_OBJ(user_data)) {
+ /* Sanity checks. */
+ return NULL;
+ }
+
+ flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
+ __ao2_callback(c, flags, ao2_match_by_addr, user_data);
+
+ return NULL;
+}
+
+/*!
+ * \brief special callback that matches all
+ */
+static int cb_true(void *user_data, void *arg, int flags)
+{
+ return CMP_MATCH;
+}
+
+/*!
+ * \brief similar to cb_true, but is an ao2_callback_data_fn instead
+ */
+static int cb_true_data(void *user_data, void *arg, void *data, int flags)
+{
+ return CMP_MATCH;
+}
+
+void *__ao2_callback_debug(struct ao2_container *c, enum search_flags flags,
+ ao2_callback_fn *cb_fn, void *arg, const char *tag, const char *file, int line,
+ const char *func)
+{
+ if (!INTERNAL_OBJ(c) || !c->v_table || !c->v_table->traverse) {
+ /* Sanity checks. */
+ return NULL;
+ }
+ return c->v_table->traverse(c, flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, func);
+}
+
+void *__ao2_callback(struct ao2_container *c, enum search_flags flags,
+ ao2_callback_fn *cb_fn, void *arg)
+{
+ if (!INTERNAL_OBJ(c) || !c->v_table || !c->v_table->traverse) {
+ /* Sanity checks. */
+ return NULL;
+ }
+ return c->v_table->traverse(c, flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
+}
+
+void *__ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags,
+ ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag, const char *file,
+ int line, const char *func)
+{
+ if (!INTERNAL_OBJ(c) || !c->v_table || !c->v_table->traverse) {
+ /* Sanity checks. */
+ return NULL;
+ }
+ return c->v_table->traverse(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, func);
+}
+
+void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
+ ao2_callback_data_fn *cb_fn, void *arg, void *data)
+{
+ if (!INTERNAL_OBJ(c) || !c->v_table || !c->v_table->traverse) {
+ /* Sanity checks. */
+ return NULL;
+ }
+ return c->v_table->traverse(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
+}
+
+/*!
+ * the find function just invokes the default callback with some reasonable flags.
+ */
+void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_flags flags,
+ const char *tag, const char *file, int line, const char *func)
+{
+ void *arged = (void *) arg;/* Done to avoid compiler const warning */
+
+ return __ao2_callback_debug(c, flags, c->cmp_fn, arged, tag, file, line, func);
+}
+
+void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags)
+{
+ void *arged = (void *) arg;/* Done to avoid compiler const warning */
+
+ return __ao2_callback(c, flags, c->cmp_fn, arged);
+}
+
+/*!
+ * initialize an iterator so we start from the first object
+ */
+struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
+{
+ struct ao2_iterator a = {
+ .c = c,
+ .flags = flags
+ };
+
+ ao2_ref(c, +1);
+
+ return a;
+}
+
+/*!
+ * destroy an iterator
+ */
+void ao2_iterator_destroy(struct ao2_iterator *iter)
+{
+ ao2_ref(iter->c, -1);
+ if (iter->flags & AO2_ITERATOR_MALLOCD) {
+ ast_free(iter);
+ } else {
+ iter->c = NULL;
+ }
+}
+
+/*
+ * move to the next element in the container.
+ */
+static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
+{
+ enum ao2_lock_req orig_lock;
+ void *ret;
+
+ if (!INTERNAL_OBJ(iter->c) || !iter->c->v_table || !iter->c->v_table->iterator_next) {
+ /* Sanity checks. */
+ return NULL;
+ }
+
+ if (iter->flags & AO2_ITERATOR_DONTLOCK) {
+ if (iter->flags & AO2_ITERATOR_UNLINK) {
+ orig_lock = adjust_lock(iter->c, AO2_LOCK_REQ_WRLOCK, 1);
+ } else {
+ orig_lock = adjust_lock(iter->c, AO2_LOCK_REQ_RDLOCK, 1);
+ }
+ } else {
+ orig_lock = AO2_LOCK_REQ_MUTEX;
+ if (iter->flags & AO2_ITERATOR_UNLINK) {
+ ao2_wrlock(iter->c);
+ } else {
+ ao2_rdlock(iter->c);
+ }
+ }
+
+ ret = iter->c->v_table->iterator_next(iter->c, iter, tag, file, line, func);
+
+ if (iter->flags & AO2_ITERATOR_DONTLOCK) {
+ adjust_lock(iter->c, orig_lock, 0);
+ } else {
+ ao2_unlock(iter->c);
+ }
+
+ return ret;
+}
+
+void *__ao2_iterator_next_debug(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
+{
+ return internal_ao2_iterator_next(iter, tag, file, line, func);
+}
+
+void *__ao2_iterator_next(struct ao2_iterator *iter)
+{
+ return internal_ao2_iterator_next(iter, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
+}
+
+static void container_destruct(void *_c)
+{
+ struct ao2_container *c = _c;
+
+ /* Unlink any stored objects in the container. */
+ c->destroying = 1;
+ __ao2_callback(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
+
+ /* Perform any extra container cleanup. */
+ if (c->v_table && c->v_table->destroy) {
+ c->v_table->destroy(c);
+ }
+
+#ifdef AO2_DEBUG
+ ast_atomic_fetchadd_int(&ao2.total_containers, -1);
+#endif
+}
+
+static void container_destruct_debug(void *_c)
+{
+ struct ao2_container *c = _c;
+
+ /* Unlink any stored objects in the container. */
+ c->destroying = 1;
+ __ao2_callback_debug(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL,
+ "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
+
+ /* Perform any extra container cleanup. */
+ if (c->v_table && c->v_table->destroy) {
+ c->v_table->destroy(c);
+ }
+
+#ifdef AO2_DEBUG
+ ast_atomic_fetchadd_int(&ao2.total_containers, -1);
+#endif
+}
+
+/*!
+ * \internal
+ * \brief Put obj into the arg container.
+ * \since 11.0
+ *
+ * \param obj pointer to the (user-defined part) of an object.
+ * \param arg callback argument from ao2_callback()
+ * \param flags flags from ao2_callback()
+ *
+ * \retval 0 on success.
+ * \retval CMP_STOP|CMP_MATCH on error.
+ */
+static int dup_obj_cb(void *obj, void *arg, int flags)
+{
+ struct ao2_container *dest = arg;
+
+ return __ao2_link(dest, obj, OBJ_NOLOCK) ? 0 : (CMP_MATCH | CMP_STOP);
+}
+
+int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
+{
+ void *obj;
+ int res = 0;
+
+ if (!(flags & OBJ_NOLOCK)) {
+ ao2_rdlock(src);
+ ao2_wrlock(dest);
+ }
+ obj = __ao2_callback(src, OBJ_NOLOCK, dup_obj_cb, dest);
+ if (obj) {
+ /* Failed to put this obj into the dest container. */
+ __ao2_ref(obj, -1);
+
+ /* Remove all items from the dest container. */
+ __ao2_callback(dest, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL,
+ NULL);
+ res = -1;
+ }
+ if (!(flags & OBJ_NOLOCK)) {
+ ao2_unlock(dest);
+ ao2_unlock(src);
+ }
+
+ return res;
+}
+
+struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags)
+{
+ struct ao2_container *clone;
+ int failed;
+
+ /* Create the clone container with the same properties as the original. */
+ if (!INTERNAL_OBJ(orig) || !orig->v_table || !orig->v_table->alloc_empty_clone) {
+ /* Sanity checks. */
+ return NULL;
+ }
+ clone = orig->v_table->alloc_empty_clone(orig);
+ if (!clone) {
+ return NULL;
+ }
+
+ if (flags & OBJ_NOLOCK) {
+ ao2_wrlock(clone);
+ }
+ failed = ao2_container_dup(clone, orig, flags);
+ if (flags & OBJ_NOLOCK) {
+ ao2_unlock(clone);
+ }
+ if (failed) {
+ /* Object copy into the clone container failed. */
+ __ao2_ref(clone, -1);
+ clone = NULL;
+ }
+ return clone;
+}
+
+struct ao2_container *__ao2_container_clone_debug(struct ao2_container *orig, enum search_flags flags, const char *tag, const char *file, int line, const char *func, int ref_debug)
+{
+ struct ao2_container *clone;
+ int failed;
+
+ /* Create the clone container with the same properties as the original. */
+ if (!INTERNAL_OBJ(orig) || !orig->v_table || !orig->v_table->alloc_empty_clone_debug) {
+ /* Sanity checks. */
+ return NULL;
+ }
+ clone = orig->v_table->alloc_empty_clone_debug(orig, tag, file, line, func, ref_debug);
+ if (!clone) {
+ return NULL;
+ }
+
+ if (flags & OBJ_NOLOCK) {
+ ao2_wrlock(clone);
+ }
+ failed = ao2_container_dup(clone, orig, flags);
+ if (flags & OBJ_NOLOCK) {
+ ao2_unlock(clone);
+ }
+ if (failed) {
+ /* Object copy into the clone container failed. */
+ if (ref_debug) {
+ __ao2_ref_debug(clone, -1, tag, file, line, func);
+ } else {
+ __ao2_ref(clone, -1);
+ }
+ clone = NULL;
+ }
+ return clone;
+}
+
+/*!
* A structure to create a linked list of entries,
* used within a bucket.
* XXX \todo this should be private to the container code
@@ -914,15 +1279,78 @@
};
/*!
- * return the number of elements in the container
- */
-int ao2_container_count(struct ao2_container *c)
-{
- return c->elements;
-}
-
-/*
- * link an object to a container
+ * \internal
+ * \brief Create an empty copy of this container.
+ * \since 11.0
+ *
+ * \param self Container to operate upon.
+ *
+ * \retval empty-clone-container on success.
+ * \retval NULL on error.
+ */
+static struct ao2_container *hash_ao2_alloc_empty_clone(struct ao2_container_hash *self)
+{
+ struct astobj2 *orig_obj;
+ unsigned int ao2_options;
+
+ /* Get container ao2 options. */
+ orig_obj = INTERNAL_OBJ(self);
+ if (!orig_obj) {
+ return NULL;
+ }
+ ao2_options = orig_obj->priv_data.options;
+
+ return __ao2_container_alloc_hash(ao2_options, self->common.options, self->n_buckets,
+ self->hash_fn, self->common.sort_fn, self->common.cmp_fn);
+}
+
+/*!
+ * \internal
+ * \brief Create an empty copy of this container. (Debug version)
+ * \since 11.0
+ *
+ * \param self Container to operate upon.
+ * \param tag used for debugging.
+ * \param file Debug file name invoked from
+ * \param line Debug line invoked from
+ * \param func Debug function name invoked from
+ * \param ref_debug TRUE if to output a debug reference message.
+ *
+ * \retval empty-clone-container on success.
+ * \retval NULL on error.
+ */
+static struct ao2_container *hash_ao2_alloc_empty_clone_debug(struct ao2_container_hash *self, const char *tag, const char *file, int line, const char *func, int ref_debug)
+{
+ struct astobj2 *orig_obj;
+ unsigned int ao2_options;
+
+ /* Get container ao2 options. */
+ orig_obj = INTERNAL_OBJ(self);
+ if (!orig_obj) {
+ return NULL;
+ }
+ ao2_options = orig_obj->priv_data.options;
+
+ return __ao2_container_alloc_hash_debug(ao2_options, self->common.options,
+ self->n_buckets, self->hash_fn, self->common.sort_fn, self->common.cmp_fn,
+ tag, file, line, func, ref_debug);
+}
+
+/*!
+ * \internal
+ * \brief Link an object into this container.
+ * \since 11.0
+ *
+ * \param self Container to operate upon.
+ * \param obj_new Object to insert into the container.
+ * \param flags search_flags to control linking the object. (OBJ_NOLOCK)
+ * \param tag used for debugging.
+ * \param file Debug file name invoked from
+ * \param line Debug line invoked from
+ * \param func Debug function name invoked from
+ *
+ * \retval 0 on errors.
+ * \retval 1 on success.
*/
static int hash_ao2_link(struct ao2_container_hash *c, void *user_data, int flags, const char *tag, const char *file, int line, const char *func)
{
@@ -970,86 +1398,34 @@
return 1;
}
-int __ao2_link_debug(struct ao2_container *c, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func)
-{
- if (!INTERNAL_OBJ(obj_new) || !INTERNAL_OBJ(c) || !c->v_table || !c->v_table->link) {
- /* Sanity checks. */
- return 0;
- }
- return c->v_table->link(c, obj_new, flags, tag, file, line, func);
-}
-
-int __ao2_link(struct ao2_container *c, void *obj_new, int flags)
-{
- if (!INTERNAL_OBJ(obj_new) || !INTERNAL_OBJ(c) || !c->v_table || !c->v_table->link) {
- /* Sanity checks. */
- return 0;
- }
- return c->v_table->link(c, obj_new, flags, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
-}
-
-/*!
- * \brief another convenience function is a callback that matches on address
- */
-int ao2_match_by_addr(void *user_data, void *arg, int flags)
-{
- return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
-}
-
-/*
- * Unlink an object from the container
- * and destroy the associated * bucket_entry structure.
- */
-void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, int flags,
- const char *tag, const char *file, int line, const char *func)
-{
- if (!INTERNAL_OBJ(user_data)) {
- /* Sanity checks. */
- return NULL;
- }
-
- flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
- __ao2_callback_debug(c, flags, ao2_match_by_addr, user_data, tag, file, line, func);
-
- return NULL;
-}
-
-void *__ao2_unlink(struct ao2_container *c, void *user_data, int flags)
-{
- if (!INTERNAL_OBJ(user_data)) {
- /* Sanity checks. */
- return NULL;
- }
-
- flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
- __ao2_callback(c, flags, ao2_match_by_addr, user_data);
-
- return NULL;
-}
-
-/*!
- * \brief special callback that matches all
- */
-static int cb_true(void *user_data, void *arg, int flags)
-{
- return CMP_MATCH;
-}
-
-/*!
- * \brief similar to cb_true, but is an ao2_callback_data_fn instead
- */
-static int cb_true_data(void *user_data, void *arg, void *data, int flags)
-{
- return CMP_MATCH;
-}
-
-/*!
+/*!
+ * \brief Traverse the container.
+ *
+ * \details
* Browse the container using different stategies accoding the flags.
- * \return Is a pointer to an object or to a list of object if OBJ_MULTIPLE is
- * specified.
* Luckily, for debug purposes, the added args (tag, file, line, func)
* aren't an excessive load to the system, as the callback should not be
* called as often as, say, the ao2_ref func is called.
+ *
+ * \param self Container to operate upon.
+ * \param flags search_flags to control traversing the container
+ * \param cb_fn Comparison callback function.
+ * \param arg Comparison callback arg parameter.
+ * \param data Data comparison callback data parameter.
+ * \param type Type of comparison callback cb_fn.
+ * \param tag used for debugging.
+ * \param file Debug file name invoked from
+ * \param line Debug line invoked from
+ * \param func Debug function name invoked from
+ *
+ * \retval NULL on failure or no matching object found.
+ *
+ * \retval object found if OBJ_MULTIPLE is not set in the flags
+ * parameter.
+ *
+ * \retval ao2_iterator pointer if OBJ_MULTIPLE is set in the
+ * flags parameter. The iterator must be destroyed with
+ * ao2_iterator_destroy() when the caller no longer needs it.
*/
static void *hash_ao2_callback(struct ao2_container_hash *c, enum search_flags flags,
void *cb_fn, void *arg, void *data, enum ao2_callback_type type, const char *tag,
@@ -1253,238 +1629,6 @@
}
}
-void *__ao2_callback_debug(struct ao2_container *c, enum search_flags flags,
- ao2_callback_fn *cb_fn, void *arg, const char *tag, const char *file, int line,
- const char *func)
-{
- if (!INTERNAL_OBJ(c) || !c->v_table || !c->v_table->traverse) {
- /* Sanity checks. */
- return NULL;
- }
- return c->v_table->traverse(c, flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, func);
-}
-
-void *__ao2_callback(struct ao2_container *c, enum search_flags flags,
- ao2_callback_fn *cb_fn, void *arg)
-{
- if (!INTERNAL_OBJ(c) || !c->v_table || !c->v_table->traverse) {
- /* Sanity checks. */
- return NULL;
- }
- return c->v_table->traverse(c, flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
-}
-
-void *__ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags,
- ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag, const char *file,
- int line, const char *func)
-{
- if (!INTERNAL_OBJ(c) || !c->v_table || !c->v_table->traverse) {
- /* Sanity checks. */
- return NULL;
- }
- return c->v_table->traverse(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, func);
-}
-
-void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
- ao2_callback_data_fn *cb_fn, void *arg, void *data)
-{
- if (!INTERNAL_OBJ(c) || !c->v_table || !c->v_table->traverse) {
- /* Sanity checks. */
- return NULL;
- }
- return c->v_table->traverse(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
-}
-
-/*!
- * the find function just invokes the default callback with some reasonable flags.
- */
-void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_flags flags,
- const char *tag, const char *file, int line, const char *func)
-{
- void *arged = (void *) arg;/* Done to avoid compiler const warning */
-
- return __ao2_callback_debug(c, flags, c->cmp_fn, arged, tag, file, line, func);
-}
-
-void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags)
-{
- void *arged = (void *) arg;/* Done to avoid compiler const warning */
-
- return __ao2_callback(c, flags, c->cmp_fn, arged);
-}
-
-/*!
- * initialize an iterator so we start from the first object
- */
-struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
-{
- struct ao2_iterator a = {
- .c = c,
- .flags = flags
- };
-
- ao2_ref(c, +1);
-
- return a;
-}
-
-/*!
- * destroy an iterator
- */
-void ao2_iterator_destroy(struct ao2_iterator *iter)
-{
- ao2_ref(iter->c, -1);
- if (iter->flags & AO2_ITERATOR_MALLOCD) {
- ast_free(iter);
- } else {
- iter->c = NULL;
- }
-}
-
-/*
- * move to the next element in the container.
- */
-static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
-{
- enum ao2_lock_req orig_lock;
- void *ret;
-
- if (!INTERNAL_OBJ(iter->c) || !iter->c->v_table || !iter->c->v_table->iterator_next) {
- /* Sanity checks. */
- return NULL;
- }
-
- if (iter->flags & AO2_ITERATOR_DONTLOCK) {
- if (iter->flags & AO2_ITERATOR_UNLINK) {
- orig_lock = adjust_lock(iter->c, AO2_LOCK_REQ_WRLOCK, 1);
- } else {
- orig_lock = adjust_lock(iter->c, AO2_LOCK_REQ_RDLOCK, 1);
- }
- } else {
- orig_lock = AO2_LOCK_REQ_MUTEX;
- if (iter->flags & AO2_ITERATOR_UNLINK) {
- ao2_wrlock(iter->c);
- } else {
- ao2_rdlock(iter->c);
- }
- }
-
- ret = iter->c->v_table->iterator_next(iter->c, iter, tag, file, line, func);
-
- if (iter->flags & AO2_ITERATOR_DONTLOCK) {
- adjust_lock(iter->c, orig_lock, 0);
- } else {
- ao2_unlock(iter->c);
- }
-
- return ret;
-}
-
-void *__ao2_iterator_next_debug(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
-{
- return internal_ao2_iterator_next(iter, tag, file, line, func);
-}
-
-void *__ao2_iterator_next(struct ao2_iterator *iter)
-{
- return internal_ao2_iterator_next(iter, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
-}
-
-static void container_destruct(void *_c)
-{
- struct ao2_container *c = _c;
-
- /* Unlink any stored objects in the container. */
- c->destroying = 1;
- __ao2_callback(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
-
- /* Perform any extra container cleanup. */
- if (c->v_table && c->v_table->destroy) {
- c->v_table->destroy(c);
- }
-
-#ifdef AO2_DEBUG
- ast_atomic_fetchadd_int(&ao2.total_containers, -1);
-#endif
-}
-
-static void container_destruct_debug(void *_c)
-{
- struct ao2_container *c = _c;
-
- /* Unlink any stored objects in the container. */
- c->destroying = 1;
- __ao2_callback_debug(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL,
- "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
-
- /* Perform any extra container cleanup. */
- if (c->v_table && c->v_table->destroy) {
- c->v_table->destroy(c);
- }
-
-#ifdef AO2_DEBUG
- ast_atomic_fetchadd_int(&ao2.total_containers, -1);
-#endif
-}
-
-/*!
- * \internal
- * \brief Create an empty copy of this container.
- * \since 11.0
- *
- * \param self Container to operate upon.
- *
- * \retval empty-clone-container on success.
- * \retval NULL on error.
- */
-static struct ao2_container *hash_ao2_alloc_empty_clone(struct ao2_container_hash *self)
-{
- struct astobj2 *orig_obj;
- unsigned int ao2_options;
-
- /* Get container ao2 options. */
- orig_obj = INTERNAL_OBJ(self);
- if (!orig_obj) {
- return NULL;
- }
- ao2_options = orig_obj->priv_data.options;
-
- return __ao2_container_alloc_hash(ao2_options, self->common.options, self->n_buckets,
- self->hash_fn, self->common.sort_fn, self->common.cmp_fn);
-}
-
-/*!
- * \internal
- * \brief Create an empty copy of this container. (Debug version)
- * \since 11.0
- *
- * \param self Container to operate upon.
- * \param tag used for debugging.
- * \param file Debug file name invoked from
- * \param line Debug line invoked from
- * \param func Debug function name invoked from
- * \param ref_debug TRUE if to output a debug reference message.
- *
- * \retval empty-clone-container on success.
- * \retval NULL on error.
- */
-static struct ao2_container *hash_ao2_alloc_empty_clone_debug(struct ao2_container_hash *self, const char *tag, const char *file, int line, const char *func, int ref_debug)
-{
- struct astobj2 *orig_obj;
- unsigned int ao2_options;
-
- /* Get container ao2 options. */
- orig_obj = INTERNAL_OBJ(self);
- if (!orig_obj) {
- return NULL;
- }
- ao2_options = orig_obj->priv_data.options;
-
- return __ao2_container_alloc_hash_debug(ao2_options, self->common.options,
- self->n_buckets, self->hash_fn, self->common.sort_fn, self->common.cmp_fn,
- tag, file, line, func, ref_debug);
-}
-
/*!
* \internal
* \brief Find the next iteration element in the container.
@@ -1703,116 +1847,6 @@
}
/*! BUGBUG need to add red-black tree container support */
-
-/*!
- * \internal
- * \brief Put obj into the arg container.
- * \since 11.0
- *
- * \param obj pointer to the (user-defined part) of an object.
- * \param arg callback argument from ao2_callback()
- * \param flags flags from ao2_callback()
- *
- * \retval 0 on success.
- * \retval CMP_STOP|CMP_MATCH on error.
- */
-static int dup_obj_cb(void *obj, void *arg, int flags)
-{
- struct ao2_container *dest = arg;
-
- return __ao2_link(dest, obj, OBJ_NOLOCK) ? 0 : (CMP_MATCH | CMP_STOP);
-}
-
-int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
-{
- void *obj;
- int res = 0;
-
- if (!(flags & OBJ_NOLOCK)) {
- ao2_rdlock(src);
- ao2_wrlock(dest);
- }
- obj = __ao2_callback(src, OBJ_NOLOCK, dup_obj_cb, dest);
- if (obj) {
- /* Failed to put this obj into the dest container. */
- __ao2_ref(obj, -1);
-
- /* Remove all items from the dest container. */
- __ao2_callback(dest, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL,
- NULL);
- res = -1;
- }
- if (!(flags & OBJ_NOLOCK)) {
- ao2_unlock(dest);
- ao2_unlock(src);
- }
-
- return res;
-}
-
-struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags)
-{
- struct ao2_container *clone;
- int failed;
-
- /* Create the clone container with the same properties as the original. */
- if (!INTERNAL_OBJ(orig) || !orig->v_table || !orig->v_table->alloc_empty_clone) {
- /* Sanity checks. */
- return NULL;
- }
- clone = orig->v_table->alloc_empty_clone(orig);
- if (!clone) {
- return NULL;
- }
-
- if (flags & OBJ_NOLOCK) {
- ao2_wrlock(clone);
- }
- failed = ao2_container_dup(clone, orig, flags);
- if (flags & OBJ_NOLOCK) {
- ao2_unlock(clone);
- }
- if (failed) {
- /* Object copy into the clone container failed. */
- __ao2_ref(clone, -1);
- clone = NULL;
- }
- return clone;
-}
-
-struct ao2_container *__ao2_container_clone_debug(struct ao2_container *orig, enum search_flags flags, const char *tag, const char *file, int line, const char *func, int ref_debug)
-{
- struct ao2_container *clone;
- int failed;
-
- /* Create the clone container with the same properties as the original. */
- if (!INTERNAL_OBJ(orig) || !orig->v_table || !orig->v_table->alloc_empty_clone_debug) {
- /* Sanity checks. */
- return NULL;
- }
- clone = orig->v_table->alloc_empty_clone_debug(orig, tag, file, line, func, ref_debug);
- if (!clone) {
- return NULL;
- }
-
- if (flags & OBJ_NOLOCK) {
- ao2_wrlock(clone);
- }
- failed = ao2_container_dup(clone, orig, flags);
- if (flags & OBJ_NOLOCK) {
- ao2_unlock(clone);
- }
- if (failed) {
- /* Object copy into the clone container failed. */
- if (ref_debug) {
- __ao2_ref_debug(clone, -1, tag, file, line, func);
- } else {
- __ao2_ref(clone, -1);
- }
- clone = NULL;
- }
- return clone;
-}
#ifdef AO2_DEBUG
static int print_cb(void *obj, void *arg, int flag)
More information about the asterisk-commits
mailing list