summaryrefslogtreecommitdiff
path: root/include/asterisk/astobj2.h
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2012-03-27 17:13:32 +0000
committerRichard Mudgett <rmudgett@digium.com>2012-03-27 17:13:32 +0000
commit38e892b370c81382dab117ef0a3a1bd2104e9520 (patch)
treef457d13a262cff01ee7f438f2d8b6e47070486ca /include/asterisk/astobj2.h
parent8611bea1224288c972a7b289ee1d18a5fa2001a4 (diff)
Add global ao2 array container.
Global ao2 objects must always exist after initialization because there is no access control to obtain another reference to the global object. It is expected that module configuration could use these new API calls to replace an active configuration parameter object with an updated configuration parameter object. With these new API calls, the global object could be replaced, removed, or referenced without the risk of someone using a stale global object pointer. Review: https://reviewboard.asterisk.org/r/1824/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@360627 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'include/asterisk/astobj2.h')
-rw-r--r--include/asterisk/astobj2.h127
1 files changed, 127 insertions, 0 deletions
diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h
index b6bea649e..4b174b05d 100644
--- a/include/asterisk/astobj2.h
+++ b/include/asterisk/astobj2.h
@@ -564,6 +564,133 @@ int __ao2_trylock(void *a, enum ao2_lock_req lock_how, const char *file, const c
*/
void *ao2_object_get_lockaddr(void *obj);
+
+/*! Global ao2 array container base structure. */
+struct ao2_global_obj {
+ /*! Access lock to the global ao2 array container. */
+ ast_rwlock_t lock;
+ /*! Number of elements in the global ao2 array container. */
+ unsigned int num_elements;
+ /*! Global ao2 array container array. */
+ void *obj[0];
+};
+
+/*!
+ * \brief Define a structure to be used to hold a global array of ao2 objects, statically initialized.
+ * \since 11.0
+ *
+ * \param name This will be the name of the defined structure.
+ * \param num_objects Number of ao2 objects to contain.
+ *
+ * \details
+ * This macro creates a structure definition that can be used to
+ * hold an array of ao2 objects accessible using an API. The
+ * structure is allocated and initialized to be empty.
+ *
+ * Example usage:
+ * \code
+ * static AO2_GLOBAL_OBJ_STATIC(global_cfg, 10);
+ * \endcode
+ *
+ * This would define \c struct \c global_cfg, intended to hold
+ * an array of ao2 objects accessible using an API.
+ */
+#ifndef HAVE_PTHREAD_RWLOCK_INITIALIZER
+#define AO2_GLOBAL_OBJ_STATIC(name, num_objects) \
+ struct name { \
+ struct ao2_global_obj global; \
+ void *objs[num_objects]; \
+ } name; \
+ static void __attribute__((constructor)) __init_##name(void) \
+ { \
+ unsigned int idx = (num_objects); \
+ ast_rwlock_init(&name.global.lock); \
+ name.global.num_elements = idx; \
+ while (idx--) { \
+ name.global.obj[idx] = NULL; \
+ } \
+ } \
+ static void __attribute__((destructor)) __fini_##name(void) \
+ { \
+ unsigned int idx = (num_objects); \
+ while (idx--) { \
+ if (name.global.obj[idx]) { \
+ ao2_ref(name.global.obj[idx], -1); \
+ name.global.obj[idx] = NULL; \
+ } \
+ } \
+ ast_rwlock_destroy(&name.global.lock); \
+ } \
+ struct __dummy_##name
+#else
+#define AO2_GLOBAL_OBJ_STATIC(name, num_objects) \
+ struct name { \
+ struct ao2_global_obj global; \
+ void *objs[num_objects]; \
+ } name = { \
+ .global.lock = AST_RWLOCK_INIT_VALUE, \
+ .global.num_elements = (num_objects), \
+ }
+#endif
+
+/*!
+ * \brief Release all global ao2 objects in the global array.
+ * \since 11.0
+ *
+ * \param array Global ao2 object array container.
+ * \param tag used for debugging
+ *
+ * \return Nothing
+ */
+#define ao2_t_global_obj_release(array, tag) \
+ __ao2_global_obj_release(&array.global, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #array)
+#define ao2_global_obj_release(array) \
+ __ao2_global_obj_release(&array.global, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #array)
+
+void __ao2_global_obj_release(struct ao2_global_obj *array, const char *tag, const char *file, int line, const char *func, const char *name);
+
+/*!
+ * \brief Replace a global ao2 object in the global array.
+ * \since 11.0
+ *
+ * \param array Global ao2 object array container.
+ * \param idx Index to replace in the array.
+ * \param obj Object to put into the array. Can be NULL.
+ * \param tag used for debugging
+ *
+ * \note This function automatically increases the reference
+ * count to account for the reference that the global array now
+ * holds to the object.
+ *
+ * \retval Reference to previous global ao2 object stored at the index.
+ * \retval NULL if no object available.
+ */
+#define ao2_t_global_obj_replace(array, idx, obj, tag) \
+ __ao2_global_obj_replace(&array.global, (idx), (obj), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #array)
+#define ao2_global_obj_replace(array, idx, obj) \
+ __ao2_global_obj_replace(&array.global, (idx), (obj), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #array)
+
+void *__ao2_global_obj_replace(struct ao2_global_obj *array, unsigned int idx, void *obj, const char *tag, const char *file, int line, const char *func, const char *name);
+
+/*!
+ * \brief Get a reference to the object stored in the ao2 global array.
+ * \since 11.0
+ *
+ * \param array Global ao2 object array container.
+ * \param idx Index to get an object reference in the array.
+ * \param tag used for debugging
+ *
+ * \retval Reference to current global ao2 object stored at the index.
+ * \retval NULL if no object available.
+ */
+#define ao2_t_global_obj_ref(array, idx, tag) \
+ __ao2_global_obj_ref(&array.global, (idx), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #array)
+#define ao2_global_obj_ref(array, idx) \
+ __ao2_global_obj_ref(&array.global, (idx), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #array)
+
+void *__ao2_global_obj_ref(struct ao2_global_obj *array, unsigned int idx, const char *tag, const char *file, int line, const char *func, const char *name);
+
+
/*!
\page AstObj2_Containers AstObj2 Containers