diff options
-rw-r--r-- | include/asterisk/astobj2.h | 23 | ||||
-rw-r--r-- | main/astobj2.c | 27 | ||||
-rw-r--r-- | tests/test_astobj2_weaken.c | 22 |
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) { |