diff options
author | Joshua Colp <jcolp@digium.com> | 2017-10-12 10:32:26 -0500 |
---|---|---|
committer | Gerrit Code Review <gerrit2@gerrit.digium.api> | 2017-10-12 10:32:26 -0500 |
commit | 765dfdc52953fef59f806599375696fc30a05c6d (patch) | |
tree | fd55cc93c577b382af713295a14a335701087044 | |
parent | 0a54ccf56aaf96386ced28c3a1e5e8c7ab9d3cbf (diff) | |
parent | 722d443275c43d5018046d6e333a2f2a8044b2ec (diff) |
Merge "astobj2: Add ao2_weakproxy_find function." into 14
-rw-r--r-- | include/asterisk/astobj2.h | 11 | ||||
-rw-r--r-- | main/astobj2_container.c | 42 |
2 files changed, 53 insertions, 0 deletions
diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h index b118d2ec0..45863c572 100644 --- a/include/asterisk/astobj2.h +++ b/include/asterisk/astobj2.h @@ -1777,6 +1777,17 @@ void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags, void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags, const char *tag, const char *file, int line, const char *func); +/*! + * \brief Perform an ao2_find on a container with ao2_weakproxy objects, returning the real object. + * + * \note Only OBJ_SEARCH_* and OBJ_NOLOCK flags are supported by this function. + * \see ao2_callback for description of arguments. + */ +#define ao2_weakproxy_find(c, arg, flags, tag) \ + __ao2_weakproxy_find(c, arg, flags, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__) +void *__ao2_weakproxy_find(struct ao2_container *c, const void *arg, enum search_flags flags, + const char *tag, const char *file, int line, const char *func); + /*! \brief * * diff --git a/main/astobj2_container.c b/main/astobj2_container.c index 15fd41286..d5e7d7bb0 100644 --- a/main/astobj2_container.c +++ b/main/astobj2_container.c @@ -439,6 +439,48 @@ void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags fla return __ao2_callback(c, flags, c->cmp_fn, arged, tag, file, line, func); } +void *__ao2_weakproxy_find(struct ao2_container *c, const void *arg, enum search_flags flags, + const char *tag, const char *file, int line, const char *func) +{ + void *proxy; + void *obj = NULL; + enum ao2_lock_req orig_lock; + + ast_assert(!!c); + ast_assert(flags & OBJ_SEARCH_MASK); + ast_assert(!(flags & ~(OBJ_SEARCH_MASK | OBJ_NOLOCK))); + + if (flags & OBJ_NOLOCK) { + orig_lock = __adjust_lock(c, AO2_LOCK_REQ_RDLOCK, 1); + } else { + orig_lock = AO2_LOCK_REQ_RDLOCK; + ao2_rdlock(c); + } + + while ((proxy = ao2_find(c, arg, flags | OBJ_NOLOCK))) { + obj = __ao2_weakproxy_get_object(proxy, 0, tag ?: __PRETTY_FUNCTION__, file, line, func); + + if (obj) { + ao2_ref(proxy, -1); + break; + } + + /* Upgrade to a write lock */ + __adjust_lock(c, AO2_LOCK_REQ_WRLOCK, 1); + ao2_unlink_flags(c, proxy, OBJ_NOLOCK); + ao2_ref(proxy, -1); + } + + if (flags & OBJ_NOLOCK) { + /* We'll keep any upgraded lock */ + __adjust_lock(c, orig_lock, 1); + } else { + ao2_unlock(c); + } + + return obj; +} + /*! * initialize an iterator so we start from the first object */ |