summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorey Farrell <git@cfware.com>2015-04-29 00:35:22 -0400
committerCorey Farrell <git@cfware.com>2015-04-29 13:28:54 -0400
commitc9c03998cc9c57acbf1998a0cbc0bc1fa6d24edb (patch)
treebd11b677fedc5ff69bbad932a55b99854c09f023
parented5715eb3994d08fdf81001dabdb39b171a308ac (diff)
Astobj2: Add ao2_weakproxy_ref_object function.
This function allows code to run ao2_ref against the real object associated with a weakproxy. It is useful when all of the following conditions are true: * You have a pointer to weakproxy. * You do not have or need a pointer to the real object. * You need to ensure the real object exists and is not destroyed during a process. In this case it's wasteful to store a pointer to the real object just for the sake of releasing it later. Change-Id: I38a319b83314de75be74207a8771aab269bcca46
-rw-r--r--include/asterisk/astobj2.h23
-rw-r--r--main/astobj2.c27
-rw-r--r--tests/test_astobj2_weaken.c22
3 files changed, 72 insertions, 0 deletions
diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h
index de35bb324..e02a4cd85 100644
--- a/include/asterisk/astobj2.h
+++ b/include/asterisk/astobj2.h
@@ -560,6 +560,29 @@ int __ao2_weakproxy_set_object(void *weakproxy, void *obj, int flags,
/*!
* \since 14.0.0
+ * \brief Run ao2_t_ref on the object associated with weakproxy.
+ *
+ * \param weakproxy The weakproxy to read from.
+ * \param delta Value to add to the reference counter.
+ * \param flags OBJ_NOLOCK to avoid locking weakproxy.
+ *
+ * \retval -2 weakproxy is not a valid ao2_weakproxy.
+ * \retval -1 weakproxy has no associated object.
+ *
+ * \return The value of the reference counter before the operation.
+ */
+int __ao2_weakproxy_ref_object(void *weakproxy, int delta, int flags,
+ const char *tag, const char *file, int line, const char *func);
+
+#define ao2_t_weakproxy_ref_object(weakproxy, delta, flags, tag) \
+ __ao2_weakproxy_ref_object(weakproxy, delta, flags, \
+ tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+#define ao2_weakproxy_ref_object(weakproxy, delta, flags) \
+ ao2_t_weakproxy_ref_object(weakproxy, delta, flags, "")
+
+/*!
+ * \since 14.0.0
* \brief Get the object associated with weakproxy.
*
* \param weakproxy The weakproxy to read from.
diff --git a/main/astobj2.c b/main/astobj2.c
index c5b5cd957..f9dd8d490 100644
--- a/main/astobj2.c
+++ b/main/astobj2.c
@@ -836,6 +836,33 @@ int __ao2_weakproxy_set_object(void *weakproxy, void *obj, int flags,
return ret;
}
+int __ao2_weakproxy_ref_object(void *weakproxy, int delta, int flags,
+ const char *tag, const char *file, int line, const char *func)
+{
+ struct astobj2 *internal = __INTERNAL_OBJ_CHECK(weakproxy, file, line, func);
+ int ret = -1;
+
+ if (!internal || internal->priv_data.magic != AO2_WEAK) {
+ /* This method is meant to be run on weakproxy objects! */
+ return -2;
+ }
+
+ /* We have a weak object, grab lock. */
+ if (!(flags & OBJ_NOLOCK)) {
+ ao2_lock(weakproxy);
+ }
+
+ if (internal->priv_data.weakptr) {
+ ret = __ao2_ref(internal->priv_data.weakptr, delta, tag, file, line, func);
+ }
+
+ if (!(flags & OBJ_NOLOCK)) {
+ ao2_unlock(weakproxy);
+ }
+
+ return ret;
+}
+
void *__ao2_weakproxy_get_object(void *weakproxy, int flags,
const char *tag, const char *file, int line, const char *func)
{
diff --git a/tests/test_astobj2_weaken.c b/tests/test_astobj2_weaken.c
index e53ab7a00..6a5eaeb99 100644
--- a/tests/test_astobj2_weaken.c
+++ b/tests/test_astobj2_weaken.c
@@ -223,7 +223,29 @@ AST_TEST_DEFINE(astobj2_weak1)
goto fail_cleanup;
}
+ if (ao2_t_weakproxy_ref_object(obj3, +1, 0, "ao2_ref should never see this") != -2) {
+ ast_test_status_update(test,
+ "Expected -2 from ao2_t_weakproxy_ref_object against normal ao2 object.\n");
+ goto fail_cleanup;
+ }
+
+ if (ao2_t_weakproxy_ref_object(weakref2, +1, 0, "weakref2 ref_object") != 2) {
+ ast_test_status_update(test, "Expected 2 from weakref2 ref_object.\n");
+ goto fail_cleanup;
+ }
+
+ if (ao2_t_ref(obj3, -1, "balance weakref2 ref_object") != 3) {
+ ast_test_status_update(test, "Expected 3 from obj3 ao2_t_ref.\n");
+ goto fail_cleanup;
+ }
+
ao2_ref(obj3, -1);
+
+ if (ao2_weakproxy_ref_object(weakref2, +1, 0) != -1) {
+ ast_test_status_update(test, "Expected -1 from weakref2 ref_object because obj3 is gone.\n");
+ goto fail_cleanup;
+ }
+
ao2_t_ref(weakref2, -1, "weakref2");
if (!weakproxydestroyed) {