[svn-commits] dvossel: branch dvossel/awesomehooks r287191 - in /team/dvossel/awesomehooks:...
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Thu Sep 16 15:35:57 CDT 2010
Author: dvossel
Date: Thu Sep 16 15:35:53 2010
New Revision: 287191
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=287191
Log:
awesomehooks are now represented by an id outside of the awesomehook api.
Modified:
team/dvossel/awesomehooks/include/asterisk/awesomehook.h
team/dvossel/awesomehooks/main/awesomehook.c
Modified: team/dvossel/awesomehooks/include/asterisk/awesomehook.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/awesomehooks/include/asterisk/awesomehook.h?view=diff&rev=287191&r1=287190&r2=287191
==============================================================================
--- team/dvossel/awesomehooks/include/asterisk/awesomehook.h (original)
+++ team/dvossel/awesomehooks/include/asterisk/awesomehook.h Thu Sep 16 15:35:53 2010
@@ -26,25 +26,22 @@
#include "asterisk/frame.h"
#include "asterisk/channel.h"
+struct ast_awesomehook;
+
struct ast_awesomehook_list {
+ unsigned int id_count;
AST_LIST_HEAD_NOLOCK(, ast_awesomehook) list;
};
-enum ast_awesomehook_status {
- AST_AWESOMEHOOK_STATUS_INIT,
- AST_AWESOMEHOOK_STATUS_ATTACHED,
- AST_AWESOMEHOOK_STATUS_DETACHED
-};
-
+/*!
+ * \brief These are the types of events that the awesomehook's event callback can receive
+ */
enum ast_awesomehook_event {
- AST_AWESOMEHOOK_EVENT_NOOP, /*!< This is a NO-OP event. It only exists to initilized the awesomehook->last_event variable*/
AST_AWESOMEHOOK_EVENT_READ, /*!< frame is intercepted in the read direction on the channel. */
AST_AWESOMEHOOK_EVENT_WRITE, /*!< frame is intercepted on the write direction on the channel. */
- AST_AWESOMEHOOK_EVENT_ATTACHED, /*!< the awesomehook is attached and running on the channel. */
- AST_AWESOMEHOOK_EVENT_DETACHED /*!< the awesomehook is detached from the channel. */
+ AST_AWESOMEHOOK_EVENT_ATTACHED, /*!< awesomehook is attached and running on the channel, the first message sent to event_cb. */
+ AST_AWESOMEHOOK_EVENT_DETACHED /*!< awesomehook is detached from the channel, last message sent to event_cb. */
};
-
-struct ast_awesomehook;
/*!
* \brief This callback is called every time an event occurs on the awesomehook.
@@ -55,85 +52,84 @@
* AST_AWESOMEHOOK_EVENT_DETACHED, which occurs right after the awesomehook is
* detached.
*
- * It is _NOT_ safe to assume the channel or the frame are ever not NULL. Always perform
- * a NULL check before performing any action on either of these objects.
+ * It is completely valid for the frame variable to be set to NULL. Always do a NULL
+ * check on the frame before attempted to access it. When the frame variable is present,
+ * it is safe to view and manipulate that frame in any way possible. It is even safe
+ * to return a completely different frame, but when that occurs this function is in
+ * charge of freeing the previous frame.
*
- * When the channel variable is present, it is safe to assume it will always be locked.
- * Never attempt to unlock the channel variable during this callback.
+ * The ast_channel will always be locked during this callback. Never attempt to unlock the
+ * channel for any reason.
*
- * When the frame variable is present, it is safe to view and manipulate that frame
- * in any way possible. It is even safe to return a completely different frame, but
- * when that occurs this function is in charge of freeing the previous frame.
- *
- * \param awesomehook, The awesomehook associated with this callback.
- * \param channel, The ast_channel this awesomehook is attached to.
+ * \param channel, The ast_channel this awesomehook is attached to
* \param frame, The ast_frame being intercepted for viewing and manipulation
* \param event, The type of event which is occurring
+ * \param datastore, The datastore pointer provided at awesomehook initilization.
*
* \retval the resulting frame.
*/
-typedef struct ast_frame *(*ast_awesomehook_event_callback)(struct ast_awesomehook *awesomehook,
+typedef struct ast_frame *(*ast_awesomehook_event_callback)(
struct ast_channel *chan,
struct ast_frame *frame,
- enum ast_awesomehook_event event);
+ enum ast_awesomehook_event event,
+ void *datastore);
/*!
* \brief This callback is called immediately before the awesomehook is destroyed.
* \note This function should be used to clean up any pointers pointing to the
* awesomehook structure as the awesomehook will be freed immediately afterwards.
+ *
+ * \param datastore, The datastore pointer provided at awesomehook initilization. This
+ * is a good place to clean up any state data allocated for the awesomehook stored in this
+ * pointer.
*/
-typedef int (*ast_awesomehook_destroy_callback)(struct ast_awesomehook *awesomehook);
-
-/*!
- * \brief Initialize a new awesomehook structure.
- *
- * \param event_cb represents the function that will be called everytime an
- * event occurs on the awesomehook.
- * \param destroy_cb is option. This function is called immediately before the
- * awesomehook is destroyed so cleanup can occur.
- *
- * \retval pointer to allocated awesomehook on Success.
- * \retval NULL on failure.
- */
-struct ast_awesomehook *ast_awesomehook_alloc(
- ast_awesomehook_event_callback event_cb,
- ast_awesomehook_destroy_callback destroy_cb);
+typedef void (*ast_awesomehook_destroy_callback)(void *datastore);
/*!
* \brief Attach an awesomehook onto a channel for frame interception.
*
- * \param ast_awesomehook to attach
- * \param ast_channel to attached the awesomehook onto.
- * \retval 0 success
- * \retval -1 failure
+ * \param ast_channel, The channel to attach the hook on to.
+ * \param event_cb represents the function that will be called everytime an
+ * event occurs on the awesomehook.
+ * \param destroy_cb is optional. This function is called immediately before the
+ * awesomehook is destroyed to allow for datastore cleanup.
+ * \param Any custom data to be stored on the awesomehook. This data pointer will
+ * be provided during each event callback which allows the awesomehook to store any
+ * stateful data associated with the application using the hook.
+ *
+ * \note XXX The Channel must be locked during this function all.
+ *
+ * \note The datastore pointer is never touched by the awesomehook API except to
+ * provide it during the event and destruction callbacks. It is entirely up to the
+ * application using this API to manage the memory associated with the datastore pointer.
+ *
+ * \retval On success, positive id representing this hook on the channel
+ * \retval On failure, -1
*/
-int ast_awesomehook_attach(struct ast_awesomehook *awesomehook, struct ast_channel *chan);
+int ast_awesomehook_attach(
+ struct ast_channel *chan,
+ ast_awesomehook_event_callback event_cb,
+ ast_awesomehook_destroy_callback destroy_cb,
+ void *datastore);
/*!
- * \brief Mark awesomehook for channel detachment and destruction.
+ * \brief Detach an awesomehook from a channel.
+ *
+ * \note XXX The Channel must be locked during this function all.
*
- * \note This function is marks the awesomehook for removal and destruction
- * by the channel thread. Once the actual destruction takes place the
- * awesomehook's destroy callback function will be called allowing for
- * any necessary cleanup to occur.
+ * \param The channel the awesomehook is attached to
+ * \param The awesomehook's id
*
- * \note After this function is used on a awesomehook, that awesomehook
- * is effectively done. It can never be re-attached to another channel.
- * The applications using the awesomehook will be still be notified via
- * the destroy_cb function once the actual destruction takes place.
- *
- * \param awesomehook to mark for detachment.
* \retval 0 success
- * \retval -1 failure
+ * \retval -1 awesomehook did not exist on the channel
*/
-int ast_awesomehook_signal_destroy(struct ast_awesomehook *awesomehook);
+int ast_awesomehook_detach(struct ast_channel *chan, int awesomehook_id);
/*!
* \brief This is used by the channel API to detach and destroy all
* awesomehooks on a channel during channel destruction.
*
- * \note XXX READ THIS! This function should only be used by the
- * Channel API. Do not call this outside the channel API.
+ * \note XXX The Channel must be locked during this function all.
*
* \param awesomehook list to destroy
* \retval 0 success
@@ -148,7 +144,7 @@
* even NULL. There is nothing to keep up with after this function. If the frame is modified, the
* awesomehook callback is in charge of any memory management associated with that modification.
*
- * \note the list's channel owner _MUST_ be locked while calling this function.
+ * \note XXX The Channel must be locked during this function all.
*
* \param awesomehook list to push event to.
* \param frame being pushed to the awesomehook list.
@@ -164,7 +160,7 @@
* even NULL. There is nothing to keep up with after this function. If the frame is modified, the
* awesomehook callback is in charge of any memory management associated with that modification.
*
- * \note the list's channel owner _MUST_ be locked while calling this function.
+ * \note XXX The Channel must be locked during this function all.
*
* \param awesomehook list to push event to.
* \param frame being pushed to the awesomehook list.
@@ -175,26 +171,12 @@
/*!
* \brief Determine if an awesomehook list is empty or not
+ *
+ * \note XXX The Channel must be locked during this function all.
+ *
* \param the awesomehook list
* \retval 0, not empty
* \retval 1, is empty
*/
int ast_awesomehook_list_is_empty(struct ast_awesomehook_list *awesomehooks);
-
-/*!
- * \brief Set the awesomehook's custom data storage pointer.
- *
- * \note A custom data pointer can be stored on an awesomehook. This allows
- * for any stateful data the event_callback may need to be sorted directly on
- * the awesomehook.
- */
-int ast_awesomehook_set_datastore(struct ast_awesomehook *awesomehook, void *data);
-
-/*!
- * \brief Return the awesomehook's custom data storage pointer.
- *
- * \return A pointer to the awesomehook's datastore data.
- */
-void *ast_awesomehook_get_datastore(struct ast_awesomehook *awesomehook);
-
#endif /* _AST_AWESOMEHOOK_H */
Modified: team/dvossel/awesomehooks/main/awesomehook.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/awesomehooks/main/awesomehook.c?view=diff&rev=287191&r1=287190&r2=287191
==============================================================================
--- team/dvossel/awesomehooks/main/awesomehook.c (original)
+++ team/dvossel/awesomehooks/main/awesomehook.c Thu Sep 16 15:35:53 2010
@@ -28,24 +28,17 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/channel.h"
-#include "asterisk/lock.h"
#include "asterisk/linkedlists.h"
#include "asterisk/awesomehook.h"
#include "asterisk/frame.h"
-#define ast_awesomehook_lock(ah) ast_mutex_lock(&(ah)->lock)
-#define ast_awesomehook_unlock(ah) ast_mutex_unlock(&(ah)->lock)
-
struct ast_awesomehook {
- ast_mutex_t lock;
- /*! Current awesomehook status. */
- enum ast_awesomehook_status status;
- /*! The last event type that went to the awesomehook event callback */
- enum ast_awesomehook_event last_event;
/*! This pointer holds any stateful data an application wishes to store. */
void *datastore;
/*! This pointer to ast_channel the awesomehook is attached to. */
struct ast_channel *chan;
+ /*! the id representing this awesomehook on a channel */
+ unsigned int id;
/*! Pointer to the registered event callback function. */
ast_awesomehook_event_callback event_cb;
/*! Pointer to the registered destruction callback function. */
@@ -54,100 +47,75 @@
AST_LIST_ENTRY(ast_awesomehook) list;
};
-static void awesomehook_update_status(struct ast_awesomehook *awesomehook, enum ast_awesomehook_status status)
-{
- /* once the status is set as DETACHED, it is forever detached and ready for destruction */
- if (awesomehook->status == AST_AWESOMEHOOK_STATUS_DETACHED) {
- return;
- }
- ast_awesomehook_lock(awesomehook);
- awesomehook->status = status;
- ast_awesomehook_unlock(awesomehook);
-}
-
-static int awesomehook_destroy(struct ast_awesomehook *awesomehook)
-{
- if (awesomehook->destroy_cb) {
- awesomehook->destroy_cb(awesomehook);
- }
- ast_mutex_destroy(&awesomehook->lock);
- ast_free(awesomehook);
- return 0;
-}
-
static void awesomehook_detach_and_destroy(struct ast_awesomehook *awesomehook)
{
struct ast_frame *frame;
- awesomehook_update_status(awesomehook, AST_AWESOMEHOOK_STATUS_DETACHED);
- frame = awesomehook->event_cb(awesomehook, awesomehook->chan, NULL, AST_AWESOMEHOOK_EVENT_DETACHED);
+ frame = awesomehook->event_cb(awesomehook->chan, NULL, AST_AWESOMEHOOK_EVENT_DETACHED, awesomehook->datastore);
/* never assume anything about this function. If you can return a frame during
* the detached event, then assume someone will. */
if (frame) {
ast_frfree(frame);
}
awesomehook->chan = NULL;
- awesomehook_destroy(awesomehook);
+
+ if (awesomehook->destroy_cb) {
+ awesomehook->destroy_cb(awesomehook->datastore);
+ }
+ ast_free(awesomehook);
}
static struct ast_frame *awesomehook_list_push_event(struct ast_awesomehook_list *awesomehooks, struct ast_frame *frame, enum ast_awesomehook_event event)
{
struct ast_awesomehook *awesomehook;
- AST_LIST_TRAVERSE_SAFE_BEGIN(&awesomehooks->list, awesomehook, list) {
- /* check to see if this hook was signaled for detachment, if so do not push the
- * read/write event. Instead detach from list and destroy */
- if (awesomehook->status == AST_AWESOMEHOOK_STATUS_DETACHED) {
- AST_LIST_REMOVE_CURRENT(list);
- awesomehook_detach_and_destroy(awesomehook);
- continue;
- }
- frame = awesomehook->event_cb(awesomehook, awesomehook->chan, frame, event);
+ AST_LIST_TRAVERSE(&awesomehooks->list, awesomehook, list) {
+ frame = awesomehook->event_cb(awesomehook->chan, frame, event, awesomehook->datastore);
}
- AST_LIST_TRAVERSE_SAFE_END;
-
return frame;
}
-struct ast_awesomehook *ast_awesomehook_alloc(ast_awesomehook_event_callback event_cb, ast_awesomehook_destroy_callback destroy_cb)
+int ast_awesomehook_attach(struct ast_channel *chan, ast_awesomehook_event_callback event_cb, ast_awesomehook_destroy_callback destroy_cb, void *data)
{
struct ast_awesomehook *awesomehook;
+ struct ast_frame *frame;
if (!event_cb || !(awesomehook = ast_calloc(1, sizeof(*awesomehook)))) {
- return NULL;
+ return -1;
}
awesomehook->event_cb = event_cb;
awesomehook->destroy_cb = destroy_cb;
- awesomehook->status = AST_AWESOMEHOOK_STATUS_INIT;
- awesomehook->last_event = AST_AWESOMEHOOK_EVENT_NOOP;
- ast_mutex_init(&awesomehook->lock);
- return awesomehook;
-}
+ awesomehook->datastore = data;
+ awesomehook->chan = chan;
+ awesomehook->id = ++chan->awesomehooks.id_count;
-int ast_awesomehook_attach(struct ast_awesomehook *awesomehook, struct ast_channel *chan)
-{
- struct ast_frame *frame;
- ast_channel_lock(chan);
AST_LIST_INSERT_TAIL(&chan->awesomehooks.list, awesomehook, list);
- awesomehook->chan = chan;
- ast_channel_unlock(chan);
- awesomehook_update_status(awesomehook, AST_AWESOMEHOOK_STATUS_ATTACHED);
+ /* Tell the event callback we're live and rocking */
+ frame = awesomehook->event_cb(awesomehook->chan, NULL, AST_AWESOMEHOOK_EVENT_ATTACHED, awesomehook->datastore);
- /* tell the event callback we're live and rocking */
- frame = awesomehook->event_cb(awesomehook, awesomehook->chan, NULL, AST_AWESOMEHOOK_EVENT_ATTACHED);
-
- /* never assume anything about this function. If you can return a frame during
+ /* Never assume anything about this function. If you can return a frame during
* the attached event, then assume someone will. */
if (frame) {
ast_frfree(frame);
}
- return 0;
+ return awesomehook->id;
}
-int ast_awesomehook_signal_destroy(struct ast_awesomehook *awesomehook)
+int ast_awesomehook_detach(struct ast_channel *chan, int id)
{
- /* This signals to the channel to detach and destroy the hook on the next read or write */
- awesomehook_update_status(awesomehook, AST_AWESOMEHOOK_STATUS_DETACHED);
- return 0;
+ struct ast_awesomehook *awesomehook;
+ int res = -1;
+
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->awesomehooks.list, awesomehook, list) {
+ if (awesomehook->id == id) {
+ AST_LIST_REMOVE_CURRENT(list);
+ awesomehook_detach_and_destroy(awesomehook);
+ res = 0;
+ break;
+ }
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+
+ return res;
}
int ast_awesomehook_list_destroy(struct ast_awesomehook_list *awesomehooks)
@@ -163,7 +131,6 @@
return 0;
}
-
int ast_awesomehook_list_is_empty(struct ast_awesomehook_list *awesomehooks)
{
return AST_LIST_EMPTY(&awesomehooks->list) ? 1 : 0;
@@ -178,14 +145,3 @@
{
return awesomehook_list_push_event(awesomehooks, frame, AST_AWESOMEHOOK_EVENT_READ);
}
-
-int ast_awesomehook_set_datastore(struct ast_awesomehook *awesomehook, void *data)
-{
- awesomehook->datastore = data;
- return 0;
-}
-
-void *ast_awesomehook_get_datastore(struct ast_awesomehook *awesomehook)
-{
- return awesomehook->datastore;
-}
More information about the svn-commits
mailing list