summaryrefslogtreecommitdiff
path: root/include/asterisk/astobj2.h
diff options
context:
space:
mode:
authorCorey Farrell <git@cfware.com>2015-04-12 04:22:41 -0400
committerCorey Farrell <git@cfware.com>2015-04-13 21:19:20 -0400
commitcb6bf3094ed715817bcab9a1c951e49c730dd817 (patch)
tree2ea1d113842c19dd7d833c63c23c78243e8b7358 /include/asterisk/astobj2.h
parenta573b77f781e2d6722c00bc3376afd809760bfc3 (diff)
astobj2: Add support for weakproxy objects.
This implements "weak" references. The weakproxy object is a real ao2 with normal reference counting of its own. When a weakproxy is pointed to a normal object they hold references to each other. The normal object is automatically freed when a single reference remains (the weakproxy). The weakproxy also supports subscriptions that will notify callbacks when it does not point to any real object. ASTERISK-24936 #close Reported by: Corey Farrell Change-Id: Ib9f73c02262488d314d9d9d62f58165b9ec43c67
Diffstat (limited to 'include/asterisk/astobj2.h')
-rw-r--r--include/asterisk/astobj2.h150
1 files changed, 150 insertions, 0 deletions
diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h
index 692cc7cb4..1c3c2e8ad 100644
--- a/include/asterisk/astobj2.h
+++ b/include/asterisk/astobj2.h
@@ -19,6 +19,7 @@
#include "asterisk/compat.h"
#include "asterisk/lock.h"
+#include "asterisk/linkedlists.h"
/*! \file
* \ref AstObj2
@@ -578,6 +579,155 @@ int __ao2_ref(void *o, int delta);
/*! @} */
+/*! \brief ao2_weakproxy
+ *
+ * @{
+ */
+struct ao2_weakproxy_notification;
+typedef void (*ao2_weakproxy_notification_cb)(void *weakproxy, void *data);
+
+/*! \brief This struct should be opaque, but it's size is needed. */
+struct ao2_weakproxy {
+ AST_LIST_HEAD_NOLOCK(, ao2_weakproxy_notification) destroyed_cb;
+};
+
+/*! \brief Macro which must be used at the beginning of weakproxy capable objects.
+ *
+ * \note The primary purpose of user defined fields on weakproxy objects is to hold
+ * immutable container keys for the real object.
+ */
+#define AO2_WEAKPROXY() struct ao2_weakproxy __weakproxy##__LINE__
+
+/*!
+ * \since 14.0.0
+ * \brief Allocate an ao2_weakproxy object
+ *
+ * \param data_size The sizeof() of the user-defined structure.
+ * \param destructor_fn The destructor function (can be NULL)
+ *
+ * \note "struct ao2_weakproxy" must be the first field of any object.
+ * This can be done by using AO2_WEAKPROXY to declare your structure.
+ */
+void *__ao2_weakproxy_alloc(size_t data_size, ao2_destructor_fn destructor_fn,
+ const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
+
+#define ao2_weakproxy_alloc(data_size, destructor_fn) \
+ __ao2_weakproxy_alloc(data_size, destructor_fn, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+#define ao2_t_weakproxy_alloc(data_size, destructor_fn, tag) \
+ __ao2_weakproxy_alloc(data_size, destructor_fn, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+/*!
+ * \since 14.0.0
+ * \brief Associate weakproxy with obj.
+ *
+ * \param weakproxy An object created by ao2_weakproxy_alloc.
+ * \param obj An ao2 object not created by ao2_weakproxy_alloc.
+ * \param flags OBJ_NOLOCK to avoid locking weakproxy.
+ *
+ * \retval 0 Success
+ * \retval -1 Failure
+ *
+ * \note obj must be newly created, this procedure is not thread safe
+ * if any other code can reach obj before this procedure ends.
+ *
+ * \note weakproxy may be previously existing, but must not currently
+ * have an object set.
+ *
+ * \note The only way to unset an object is for it to be destroyed.
+ * Any call to this function while an object is already set will fail.
+ */
+int __ao2_weakproxy_set_object(void *weakproxy, void *obj, int flags,
+ const char *tag, const char *file, int line, const char *func);
+
+#define ao2_weakproxy_set_object(weakproxy, obj, flags) \
+ __ao2_weakproxy_set_object(weakproxy, obj, flags, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+#define ao2_t_weakproxy_set_object(weakproxy, obj, flags, tag) \
+ __ao2_weakproxy_set_object(weakproxy, obj, flags, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+/*!
+ * \since 14.0.0
+ * \brief Get the object associated with weakproxy.
+ *
+ * \param weakproxy The weakproxy to read from.
+ * \param flags OBJ_NOLOCK to avoid locking weakproxy.
+ *
+ * \return A reference to the object previously set by ao2_weakproxy_set_object.
+ * \retval NULL Either no object was set or the previously set object has been freed.
+ */
+void *__ao2_weakproxy_get_object(void *weakproxy, int flags,
+ const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
+
+#define ao2_weakproxy_get_object(weakproxy, flags) \
+ __ao2_weakproxy_get_object(weakproxy, flags, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+#define ao2_t_weakproxy_get_object(weakproxy, flags, tag) \
+ __ao2_weakproxy_get_object(weakproxy, flags, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+/*!
+ * \since 14.0.0
+ * \brief Request notification when weakproxy points to NULL.
+ *
+ * \param weakproxy The weak object
+ * \param cb Procedure to call when no real object is associated
+ * \param data Passed to cb
+ * \param flags OBJ_NOLOCK to avoid locking weakproxy.
+ *
+ * \retval 0 Success
+ * \retval -1 Failure
+ *
+ * \note This procedure will allow the same cb / data pair to be added to
+ * the same weakproxy multiple times.
+ *
+ * \note It is the caller's responsibility to ensure that *data is valid
+ * until after cb() is run or ao2_weakproxy_unsubscribe is called.
+ *
+ * \note If the weakproxy currently points to NULL the callback will be run immediately,
+ * without being added to the subscriber list.
+ */
+int ao2_weakproxy_subscribe(void *weakproxy, ao2_weakproxy_notification_cb cb, void *data, int flags);
+
+/*!
+ * \since 14.0.0
+ * \brief Remove notification of real object destruction.
+ *
+ * \param weakproxy The weak object
+ * \param cb Callback to remove from destroy notification list
+ * \param data Data pointer to match
+ * \param flags OBJ_NOLOCK to avoid locking weakproxy.
+ * OBJ_MULTIPLE to remove all copies of the same cb / data pair.
+ *
+ * \return The number of subscriptions removed.
+ * \retval 0 cb / data pair not found, nothing removed.
+ * \retval -1 Failure due to invalid parameters.
+ *
+ * \note Unless flags includes OBJ_MULTIPLE, this will only remove a single copy
+ * of the cb / data pair. If it was subscribed multiple times it must be
+ * unsubscribed as many times. The OBJ_MULTIPLE flag can be used to remove
+ * matching subscriptions.
+ */
+int ao2_weakproxy_unsubscribe(void *weakproxy, ao2_weakproxy_notification_cb cb, void *data, int flags);
+
+/*!
+ * \since 14.0.0
+ * \brief Get the weakproxy attached to obj
+ *
+ * \param obj The object to retreive a weakproxy from
+ *
+ * \return The weakproxy object
+ */
+void *__ao2_get_weakproxy(void *obj,
+ const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
+
+#define ao2_get_weakproxy(obj) \
+ __ao2_get_weakproxy(obj, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+#define ao2_t_get_weakproxy(obj, tag) \
+ __ao2_get_weakproxy(obj, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+/*! @} */
+
+
/*! \brief Which lock to request. */
enum ao2_lock_req {
/*! Request the mutex lock be acquired. */