<p>Corey Farrell has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/10619">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">taskprocessor: Merge ast_taskprocessor and ast_taskprocessor_listener.<br><br>These objects are combined to eliminate the circular reference between<br>the two.<br><br>Change-Id: I105ad352cad14638009fac7bf1faab8580f1458e<br>---<br>M include/asterisk/taskprocessor.h<br>M main/taskprocessor.c<br>M main/threadpool.c<br>M tests/test_taskprocessor.c<br>4 files changed, 139 insertions(+), 211 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/19/10619/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/asterisk/taskprocessor.h b/include/asterisk/taskprocessor.h</span><br><span>index f74989a..b1226fb 100644</span><br><span>--- a/include/asterisk/taskprocessor.h</span><br><span>+++ b/include/asterisk/taskprocessor.h</span><br><span>@@ -77,31 +77,29 @@</span><br><span> TPS_REF_IF_EXISTS = (1 << 0),</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_taskprocessor_listener;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_taskprocessor_listener_callbacks {</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_taskprocessor_callbacks {</span><br><span> /*!</span><br><span> * \brief The taskprocessor has started completely</span><br><span> *</span><br><span> * This indicates that the taskprocessor is fully set up and the listener</span><br><span> * can now start interacting with it.</span><br><span> *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param listener The listener to start</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param tps The taskprocessor to start</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">- int (*start)(struct ast_taskprocessor_listener *listener);</span><br><span style="color: hsl(120, 100%, 40%);">+ int (*start)(struct ast_taskprocessor *tps);</span><br><span> /*!</span><br><span> * \brief Indicates a task was pushed to the processor</span><br><span> *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param listener The listener</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param tps The taskprocessor to start</span><br><span> * \param was_empty If non-zero, the taskprocessor was empty prior to the task being pushed</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">- void (*task_pushed)(struct ast_taskprocessor_listener *listener, int was_empty);</span><br><span style="color: hsl(120, 100%, 40%);">+ void (*task_pushed)(struct ast_taskprocessor *tps, int was_empty);</span><br><span> /*!</span><br><span> * \brief Indicates the task processor has become empty</span><br><span> *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param listener The listener</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param tps The taskprocessor to start</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">- void (*emptied)(struct ast_taskprocessor_listener *listener);</span><br><span style="color: hsl(120, 100%, 40%);">+ void (*emptied)(struct ast_taskprocessor *tps);</span><br><span> /*!</span><br><span> * \brief Indicates the taskprocessor wishes to die.</span><br><span> *</span><br><span>@@ -112,44 +110,18 @@</span><br><span> * After this callback returns, it is NOT safe to operate on the</span><br><span> * listener's reference to the taskprocessor.</span><br><span> *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param listener The listener</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param tps The taskprocessor to start</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">- void (*shutdown)(struct ast_taskprocessor_listener *listener);</span><br><span style="color: hsl(0, 100%, 40%);">- void (*dtor)(struct ast_taskprocessor_listener *listener);</span><br><span style="color: hsl(120, 100%, 40%);">+ void (*shutdown)(struct ast_taskprocessor *tps);</span><br><span style="color: hsl(120, 100%, 40%);">+ void (*dtor)(struct ast_taskprocessor *tps);</span><br><span> };</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Get a reference to the listener's taskprocessor</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * This will return the taskprocessor with its reference count increased. Release</span><br><span style="color: hsl(0, 100%, 40%);">- * the reference to this object by using ast_taskprocessor_unreference()</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param listener The listener that has the taskprocessor</span><br><span style="color: hsl(0, 100%, 40%);">- * \return The taskprocessor</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_taskprocessor *ast_taskprocessor_listener_get_tps(const struct ast_taskprocessor_listener *listener);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span> * \brief Get the user data from the listener</span><br><span style="color: hsl(0, 100%, 40%);">- * \param listener The taskprocessor listener</span><br><span style="color: hsl(0, 100%, 40%);">- * \return The listener's user data</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param tps The taskprocessor</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The taskprocessor's user data</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">-void *ast_taskprocessor_listener_get_user_data(const struct ast_taskprocessor_listener *listener);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Allocate a taskprocessor listener</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12.0.0</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * This will result in the listener being allocated with the specified</span><br><span style="color: hsl(0, 100%, 40%);">- * callbacks.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param callbacks The callbacks to assign to the listener</span><br><span style="color: hsl(0, 100%, 40%);">- * \param user_data The user data for the listener</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval NULL Failure</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval non-NULL The newly allocated taskprocessor listener</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_taskprocessor_listener *ast_taskprocessor_listener_alloc(const struct ast_taskprocessor_listener_callbacks *callbacks, void *user_data);</span><br><span style="color: hsl(120, 100%, 40%);">+void *ast_taskprocessor_get_user_data(const struct ast_taskprocessor *tps);</span><br><span> </span><br><span> /*!</span><br><span> * \brief Get a reference to a taskprocessor with the specified name and create the taskprocessor if necessary</span><br><span>@@ -179,7 +151,8 @@</span><br><span> * \retval NULL Failure</span><br><span> * \reval non-NULL success</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_taskprocessor *ast_taskprocessor_create_with_listener(const char *name, struct ast_taskprocessor_listener *listener);</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_taskprocessor *ast_taskprocessor_create_with_listener(const char *name,</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct ast_taskprocessor_callbacks *callbacks, void *user_data);</span><br><span> </span><br><span> /*!</span><br><span> * \brief Sets the local data associated with a taskprocessor.</span><br><span>diff --git a/main/taskprocessor.c b/main/taskprocessor.c</span><br><span>index 2629eab..8d00475 100644</span><br><span>--- a/main/taskprocessor.c</span><br><span>+++ b/main/taskprocessor.c</span><br><span>@@ -80,6 +80,11 @@</span><br><span> long tps_queue_high;</span><br><span> /*! \brief Taskprocessor queue */</span><br><span> AST_LIST_HEAD_NOLOCK(tps_queue, tps_task) tps_queue;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! The callbacks the taskprocessor calls into to notify of state changes */</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct ast_taskprocessor_callbacks *callbacks;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Data private to the listener */</span><br><span style="color: hsl(120, 100%, 40%);">+ void *user_data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct ast_taskprocessor_listener *listener;</span><br><span> /*! Current thread executing the tasks */</span><br><span> pthread_t thread;</span><br><span>@@ -104,12 +109,8 @@</span><br><span> * the module using the taskprocessor.</span><br><span> */</span><br><span> struct ast_taskprocessor_listener {</span><br><span style="color: hsl(0, 100%, 40%);">- /*! The callbacks the taskprocessor calls into to notify of state changes */</span><br><span style="color: hsl(0, 100%, 40%);">- const struct ast_taskprocessor_listener_callbacks *callbacks;</span><br><span> /*! The taskprocessor that the listener is listening to */</span><br><span> struct ast_taskprocessor *tps;</span><br><span style="color: hsl(0, 100%, 40%);">- /*! Data private to the listener */</span><br><span style="color: hsl(0, 100%, 40%);">- void *user_data;</span><br><span> };</span><br><span> </span><br><span> #ifdef LOW_MEMORY</span><br><span>@@ -157,24 +158,21 @@</span><br><span> ast_free(pvt);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void default_listener_pvt_dtor(struct ast_taskprocessor_listener *listener)</span><br><span style="color: hsl(120, 100%, 40%);">+static void default_listener_pvt_dtor(struct ast_taskprocessor *tps)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct default_taskprocessor_listener_pvt *pvt = listener->user_data;</span><br><span style="color: hsl(120, 100%, 40%);">+ default_listener_pvt_destroy(tps->user_data);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- default_listener_pvt_destroy(pvt);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- listener->user_data = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ tps->user_data = NULL;</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span> * \brief Function that processes tasks in the taskprocessor</span><br><span> * \internal</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">-static void *default_tps_processing_function(void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+static void *default_tps_processing_function(void *obj)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_taskprocessor_listener *listener = data;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_taskprocessor *tps = listener->tps;</span><br><span style="color: hsl(0, 100%, 40%);">- struct default_taskprocessor_listener_pvt *pvt = listener->user_data;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_taskprocessor *tps = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct default_taskprocessor_listener_pvt *pvt = tps->user_data;</span><br><span> int sem_value;</span><br><span> int res;</span><br><span> </span><br><span>@@ -194,25 +192,25 @@</span><br><span> ast_assert(res == 0 && sem_value == 0);</span><br><span> </span><br><span> /* Free the shutdown reference (see default_listener_shutdown) */</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_t_ref(listener->tps, -1, "tps-shutdown");</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_t_ref(tps, -1, "tps-shutdown");</span><br><span> </span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int default_listener_start(struct ast_taskprocessor_listener *listener)</span><br><span style="color: hsl(120, 100%, 40%);">+static int default_listener_start(struct ast_taskprocessor *tps)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct default_taskprocessor_listener_pvt *pvt = listener->user_data;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct default_taskprocessor_listener_pvt *pvt = tps->user_data;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_pthread_create(&pvt->poll_thread, NULL, default_tps_processing_function, listener)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_pthread_create(&pvt->poll_thread, NULL, default_tps_processing_function, tps)) {</span><br><span> return -1;</span><br><span> }</span><br><span> </span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void default_task_pushed(struct ast_taskprocessor_listener *listener, int was_empty)</span><br><span style="color: hsl(120, 100%, 40%);">+static void default_task_pushed(struct ast_taskprocessor *tps, int was_empty)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct default_taskprocessor_listener_pvt *pvt = listener->user_data;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct default_taskprocessor_listener_pvt *pvt = tps->user_data;</span><br><span> </span><br><span> if (ast_sem_post(&pvt->sem) != 0) {</span><br><span> ast_log(LOG_ERROR, "Failed to notify of enqueued task: %s\n",</span><br><span>@@ -227,15 +225,15 @@</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void default_listener_shutdown(struct ast_taskprocessor_listener *listener)</span><br><span style="color: hsl(120, 100%, 40%);">+static void default_listener_shutdown(struct ast_taskprocessor *tps)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct default_taskprocessor_listener_pvt *pvt = listener->user_data;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct default_taskprocessor_listener_pvt *pvt = tps->user_data;</span><br><span> int res;</span><br><span> </span><br><span> /* Hold a reference during shutdown */</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_t_ref(listener->tps, +1, "tps-shutdown");</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_t_ref(tps, +1, "tps-shutdown");</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_taskprocessor_push(listener->tps, default_listener_die, pvt)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_taskprocessor_push(tps, default_listener_die, pvt)) {</span><br><span> /* This will cause the thread to exit early without completing tasks already</span><br><span> * in the queue. This is probably the least bad option in this situation. */</span><br><span> default_listener_die(pvt);</span><br><span>@@ -257,7 +255,7 @@</span><br><span> pvt->poll_thread = AST_PTHREADT_NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static const struct ast_taskprocessor_listener_callbacks default_listener_callbacks = {</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct ast_taskprocessor_callbacks default_listener_callbacks = {</span><br><span> .start = default_listener_start,</span><br><span> .task_pushed = default_task_pushed,</span><br><span> .shutdown = default_listener_shutdown,</span><br><span>@@ -642,8 +640,10 @@</span><br><span> </span><br><span> ast_free((char *) t->name);</span><br><span> t->name = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_cleanup(t->listener);</span><br><span style="color: hsl(0, 100%, 40%);">- t->listener = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (t->callbacks->dtor) {</span><br><span style="color: hsl(120, 100%, 40%);">+ t->callbacks->dtor(t);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> }</span><br><span> </span><br><span> /* pop the front task and return it */</span><br><span>@@ -676,44 +676,9 @@</span><br><span> return tps->name;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void listener_shutdown(struct ast_taskprocessor_listener *listener)</span><br><span style="color: hsl(120, 100%, 40%);">+void *ast_taskprocessor_get_user_data(const struct ast_taskprocessor *tps)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- listener->callbacks->shutdown(listener);</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(listener->tps, -1);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void taskprocessor_listener_dtor(void *obj)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_taskprocessor_listener *listener = obj;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (listener->callbacks->dtor) {</span><br><span style="color: hsl(0, 100%, 40%);">- listener->callbacks->dtor(listener);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_taskprocessor_listener *ast_taskprocessor_listener_alloc(const struct ast_taskprocessor_listener_callbacks *callbacks, void *user_data)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_taskprocessor_listener *listener;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- listener = ao2_alloc(sizeof(*listener), taskprocessor_listener_dtor);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!listener) {</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- listener->callbacks = callbacks;</span><br><span style="color: hsl(0, 100%, 40%);">- listener->user_data = user_data;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return listener;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_taskprocessor *ast_taskprocessor_listener_get_tps(const struct ast_taskprocessor_listener *listener)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(listener->tps, +1);</span><br><span style="color: hsl(0, 100%, 40%);">- return listener->tps;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void *ast_taskprocessor_listener_get_user_data(const struct ast_taskprocessor_listener *listener)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return listener->user_data;</span><br><span style="color: hsl(120, 100%, 40%);">+ return tps->user_data;</span><br><span> }</span><br><span> </span><br><span> static void *default_listener_pvt_alloc(void)</span><br><span>@@ -733,16 +698,33 @@</span><br><span> return pvt;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static struct ast_taskprocessor *__allocate_taskprocessor(const char *name, struct ast_taskprocessor_listener *listener)</span><br><span style="color: hsl(120, 100%, 40%);">+static void tps_fake_shutdown(const struct ast_taskprocessor_callbacks *callbacks, void *user_data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_taskprocessor tps = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .user_data = user_data</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (callbacks->dtor) {</span><br><span style="color: hsl(120, 100%, 40%);">+ callbacks->dtor(&tps);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_taskprocessor *__allocate_taskprocessor(const char *name,</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct ast_taskprocessor_callbacks *callbacks, void *user_data)</span><br><span> {</span><br><span> struct ast_taskprocessor *p;</span><br><span> </span><br><span> p = ao2_alloc(sizeof(*p), tps_taskprocessor_dtor);</span><br><span> if (!p) {</span><br><span> ast_log(LOG_WARNING, "failed to create taskprocessor '%s'\n", name);</span><br><span style="color: hsl(120, 100%, 40%);">+ tps_fake_shutdown(callbacks, user_data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ p->callbacks = callbacks;</span><br><span style="color: hsl(120, 100%, 40%);">+ p->user_data = user_data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Set default congestion water level alert triggers. */</span><br><span> p->tps_queue_low = (AST_TASKPROCESSOR_HIGH_WATER_LEVEL * 9) / 10;</span><br><span> p->tps_queue_high = AST_TASKPROCESSOR_HIGH_WATER_LEVEL;</span><br><span>@@ -753,22 +735,15 @@</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(listener, +1);</span><br><span style="color: hsl(0, 100%, 40%);">- p->listener = listener;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> p->thread = AST_PTHREADT_NULL;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(p, +1);</span><br><span style="color: hsl(0, 100%, 40%);">- listener->tps = p;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> if (!(ao2_link(tps_singletons, p))) {</span><br><span> ast_log(LOG_ERROR, "Failed to add taskprocessor '%s' to container\n", p->name);</span><br><span style="color: hsl(0, 100%, 40%);">- listener->tps = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(p, -2);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(p, -1);</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (p->listener->callbacks->start(p->listener)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (p->callbacks->start(p)) {</span><br><span> ast_log(LOG_ERROR, "Unable to start taskprocessor listener for taskprocessor %s\n",</span><br><span> p->name);</span><br><span> ast_taskprocessor_unreference(p);</span><br><span>@@ -784,7 +759,6 @@</span><br><span> struct ast_taskprocessor *ast_taskprocessor_get(const char *name, enum ast_tps_options create)</span><br><span> {</span><br><span> struct ast_taskprocessor *p;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_taskprocessor_listener *listener;</span><br><span> struct default_taskprocessor_listener_pvt *pvt;</span><br><span> </span><br><span> if (ast_strlen_zero(name)) {</span><br><span>@@ -799,36 +773,32 @@</span><br><span> /* calling function does not want a new taskprocessor to be created if it doesn't already exist */</span><br><span> return NULL;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- /* Create a new taskprocessor. Start by creating a default listener */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> pvt = default_listener_pvt_alloc();</span><br><span> if (!pvt) {</span><br><span> return NULL;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- listener = ast_taskprocessor_listener_alloc(&default_listener_callbacks, pvt);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!listener) {</span><br><span style="color: hsl(0, 100%, 40%);">- default_listener_pvt_destroy(pvt);</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- p = __allocate_taskprocessor(name, listener);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(listener, -1);</span><br><span style="color: hsl(0, 100%, 40%);">- return p;</span><br><span style="color: hsl(120, 100%, 40%);">+ return __allocate_taskprocessor(name, &default_listener_callbacks, pvt);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_taskprocessor *ast_taskprocessor_create_with_listener(const char *name, struct ast_taskprocessor_listener *listener)</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_taskprocessor *ast_taskprocessor_create_with_listener(const char *name,</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct ast_taskprocessor_callbacks *callbacks, void *user_data)</span><br><span> {</span><br><span> struct ast_taskprocessor *p = ao2_find(tps_singletons, name, OBJ_KEY);</span><br><span> </span><br><span> if (p) {</span><br><span> ast_taskprocessor_unreference(p);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ tps_fake_shutdown(callbacks, user_data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> return NULL;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- return __allocate_taskprocessor(name, listener);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return __allocate_taskprocessor(name, callbacks, user_data);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void ast_taskprocessor_set_local(struct ast_taskprocessor *tps,</span><br><span style="color: hsl(0, 100%, 40%);">- void *local_data)</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_taskprocessor_set_local(struct ast_taskprocessor *tps, void *local_data)</span><br><span> {</span><br><span> SCOPED_AO2LOCK(lock, tps);</span><br><span> tps->local_data = local_data;</span><br><span>@@ -847,20 +817,23 @@</span><br><span> */</span><br><span> ao2_lock(tps_singletons);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (ao2_ref(tps, -1) > 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ao2_ref(tps, -1) > 2) {</span><br><span> ao2_unlock(tps_singletons);</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* If we're down to 3 references, then those must be:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* If we're down to 2 references, then those must be:</span><br><span> * 1. The reference we just got rid of</span><br><span> * 2. The container</span><br><span style="color: hsl(0, 100%, 40%);">- * 3. The listener</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_unlink_flags(tps_singletons, tps, OBJ_NOLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Steal the container reference */</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_find(tps_singletons, tps, OBJ_UNLINK | OBJ_POINTER | OBJ_NOLOCK);</span><br><span> ao2_unlock(tps_singletons);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- listener_shutdown(tps->listener);</span><br><span style="color: hsl(120, 100%, 40%);">+ tps->callbacks->shutdown(tps);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(tps, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span>@@ -897,7 +870,7 @@</span><br><span> /* The currently executing task counts as still in queue */</span><br><span> was_empty = tps->executing ? 0 : previous_size == 0;</span><br><span> ao2_unlock(tps);</span><br><span style="color: hsl(0, 100%, 40%);">- tps->listener->callbacks->task_pushed(tps->listener, was_empty);</span><br><span style="color: hsl(120, 100%, 40%);">+ tps->callbacks->task_pushed(tps, was_empty);</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span>@@ -986,8 +959,8 @@</span><br><span> ao2_unlock(tps);</span><br><span> </span><br><span> /* If we executed a task, check for the transition to empty */</span><br><span style="color: hsl(0, 100%, 40%);">- if (size == 0 && tps->listener->callbacks->emptied) {</span><br><span style="color: hsl(0, 100%, 40%);">- tps->listener->callbacks->emptied(tps->listener);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (size == 0 && tps->callbacks->emptied) {</span><br><span style="color: hsl(120, 100%, 40%);">+ tps->callbacks->emptied(tps);</span><br><span> }</span><br><span> return size > 0;</span><br><span> }</span><br><span>diff --git a/main/threadpool.c b/main/threadpool.c</span><br><span>index 7729930..dc618f9 100644</span><br><span>--- a/main/threadpool.c</span><br><span>+++ b/main/threadpool.c</span><br><span>@@ -386,6 +386,10 @@</span><br><span> static void threadpool_destructor(void *obj)</span><br><span> {</span><br><span> struct ast_threadpool *pool = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(pool->active_threads);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(pool->idle_threads);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(pool->zombie_threads);</span><br><span> ao2_cleanup(pool->listener);</span><br><span> }</span><br><span> </span><br><span>@@ -438,7 +442,7 @@</span><br><span> return pool;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int threadpool_tps_start(struct ast_taskprocessor_listener *listener)</span><br><span style="color: hsl(120, 100%, 40%);">+static int threadpool_tps_start(struct ast_taskprocessor *tps)</span><br><span> {</span><br><span> return 0;</span><br><span> }</span><br><span>@@ -604,10 +608,9 @@</span><br><span> * \param listener The taskprocessor listener. The threadpool is the listener's private data</span><br><span> * \param was_empty True if the taskprocessor was empty prior to the task being pushed</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">-static void threadpool_tps_task_pushed(struct ast_taskprocessor_listener *listener,</span><br><span style="color: hsl(0, 100%, 40%);">- int was_empty)</span><br><span style="color: hsl(120, 100%, 40%);">+static void threadpool_tps_task_pushed(struct ast_taskprocessor *tps, int was_empty)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_threadpool *pool = ast_taskprocessor_listener_get_user_data(listener);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_threadpool *pool = ast_taskprocessor_get_user_data(tps);</span><br><span> struct task_pushed_data *tpd;</span><br><span> SCOPED_AO2LOCK(lock, pool);</span><br><span> </span><br><span>@@ -648,9 +651,9 @@</span><br><span> * the threadpool no longer contains any tasks.</span><br><span> * \param listener The taskprocessor listener. The threadpool is the listener's private data.</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">-static void threadpool_tps_emptied(struct ast_taskprocessor_listener *listener)</span><br><span style="color: hsl(120, 100%, 40%);">+static void threadpool_tps_emptied(struct ast_taskprocessor *tps)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_threadpool *pool = ast_taskprocessor_listener_get_user_data(listener);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_threadpool *pool = ast_taskprocessor_get_user_data(tps);</span><br><span> SCOPED_AO2LOCK(lock, pool);</span><br><span> </span><br><span> if (pool->shutting_down) {</span><br><span>@@ -673,27 +676,31 @@</span><br><span> * in outright destroying the worker threads here.</span><br><span> * \param listener The taskprocessor listener. The threadpool is the listener's private data.</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">-static void threadpool_tps_shutdown(struct ast_taskprocessor_listener *listener)</span><br><span style="color: hsl(120, 100%, 40%);">+static void threadpool_tps_shutdown(struct ast_taskprocessor *tps)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_threadpool *pool = ast_taskprocessor_listener_get_user_data(listener);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_threadpool *pool = ast_taskprocessor_get_user_data(tps);</span><br><span> </span><br><span> if (pool->listener && pool->listener->callbacks->shutdown) {</span><br><span> pool->listener->callbacks->shutdown(pool->listener);</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_cleanup(pool->active_threads);</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_cleanup(pool->idle_threads);</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_cleanup(pool->zombie_threads);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void threadpool_tps_dtor(struct ast_taskprocessor *tps)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_threadpool *pool = ast_taskprocessor_get_user_data(tps);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> ao2_cleanup(pool);</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span> * \brief Table of taskprocessor listener callbacks for threadpool's main taskprocessor</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct ast_taskprocessor_listener_callbacks threadpool_tps_listener_callbacks = {</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_taskprocessor_callbacks threadpool_tps_listener_callbacks = {</span><br><span> .start = threadpool_tps_start,</span><br><span> .task_pushed = threadpool_tps_task_pushed,</span><br><span> .emptied = threadpool_tps_emptied,</span><br><span> .shutdown = threadpool_tps_shutdown,</span><br><span style="color: hsl(120, 100%, 40%);">+ .dtor = threadpool_tps_dtor,</span><br><span> };</span><br><span> </span><br><span> /*!</span><br><span>@@ -913,37 +920,26 @@</span><br><span> struct ast_threadpool_listener *listener,</span><br><span> const struct ast_threadpool_options *options)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_taskprocessor *tps;</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct ast_taskprocessor_listener *, tps_listener, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct ast_threadpool *, pool, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- pool = threadpool_alloc(name, options);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!pool) {</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- tps_listener = ast_taskprocessor_listener_alloc(&threadpool_tps_listener_callbacks, pool);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!tps_listener) {</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_threadpool *pool;</span><br><span> </span><br><span> if (options->version != AST_THREADPOOL_OPTIONS_VERSION) {</span><br><span> ast_log(LOG_WARNING, "Incompatible version of threadpool options in use.\n");</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- tps = ast_taskprocessor_create_with_listener(name, tps_listener);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!tps) {</span><br><span style="color: hsl(120, 100%, 40%);">+ pool = threadpool_alloc(name, options);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!pool) {</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- pool->tps = tps;</span><br><span style="color: hsl(0, 100%, 40%);">- if (listener) {</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(listener, +1);</span><br><span style="color: hsl(0, 100%, 40%);">- pool->listener = listener;</span><br><span style="color: hsl(120, 100%, 40%);">+ pool->tps = ast_taskprocessor_create_with_listener(name, &threadpool_tps_listener_callbacks, pool);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!pool->tps) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ pool->listener = ao2_bump(listener);</span><br><span> ast_threadpool_set_size(pool, pool->options.initial_size);</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(pool, +1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> return pool;</span><br><span> }</span><br><span> </span><br><span>@@ -1313,7 +1309,7 @@</span><br><span> struct ast_serializer_shutdown_group *shutdown_group;</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void serializer_dtor(void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+static void serializer_destructor(void *obj)</span><br><span> {</span><br><span> struct serializer *ser = obj;</span><br><span> </span><br><span>@@ -1328,7 +1324,7 @@</span><br><span> {</span><br><span> struct serializer *ser;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ser = ao2_alloc_options(sizeof(*ser), serializer_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+ ser = ao2_alloc_options(sizeof(*ser), serializer_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span> if (!ser) {</span><br><span> return NULL;</span><br><span> }</span><br><span>@@ -1354,38 +1350,44 @@</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void serializer_task_pushed(struct ast_taskprocessor_listener *listener, int was_empty)</span><br><span style="color: hsl(120, 100%, 40%);">+static void serializer_task_pushed(struct ast_taskprocessor *tps, int was_empty)</span><br><span> {</span><br><span> if (was_empty) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct serializer *ser = ast_taskprocessor_listener_get_user_data(listener);</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_taskprocessor *tps = ast_taskprocessor_listener_get_tps(listener);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct serializer *ser = ast_taskprocessor_get_user_data(tps);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_threadpool_push(ser->pool, execute_tasks, tps)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_threadpool_push(ser->pool, execute_tasks, ao2_bump(tps))) {</span><br><span> ast_taskprocessor_unreference(tps);</span><br><span> }</span><br><span> }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int serializer_start(struct ast_taskprocessor_listener *listener)</span><br><span style="color: hsl(120, 100%, 40%);">+static int serializer_start(struct ast_taskprocessor *tps)</span><br><span> {</span><br><span> /* No-op */</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void serializer_shutdown(struct ast_taskprocessor_listener *listener)</span><br><span style="color: hsl(120, 100%, 40%);">+static void serializer_shutdown(struct ast_taskprocessor *tps)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct serializer *ser = ast_taskprocessor_listener_get_user_data(listener);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct serializer *ser = ast_taskprocessor_get_user_data(tps);</span><br><span> </span><br><span> if (ser->shutdown_group) {</span><br><span> serializer_shutdown_group_dec(ser->shutdown_group);</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void serializer_dtor(struct ast_taskprocessor *tps)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct serializer *ser = ast_taskprocessor_get_user_data(tps);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> ao2_cleanup(ser);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static struct ast_taskprocessor_listener_callbacks serializer_tps_listener_callbacks = {</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_taskprocessor_callbacks serializer_tps_listener_callbacks = {</span><br><span> .task_pushed = serializer_task_pushed,</span><br><span> .start = serializer_start,</span><br><span> .shutdown = serializer_shutdown,</span><br><span style="color: hsl(120, 100%, 40%);">+ .dtor = serializer_dtor,</span><br><span> };</span><br><span> </span><br><span> struct ast_taskprocessor *ast_threadpool_serializer_get_current(void)</span><br><span>@@ -1397,7 +1399,6 @@</span><br><span> struct ast_threadpool *pool, struct ast_serializer_shutdown_group *shutdown_group)</span><br><span> {</span><br><span> struct serializer *ser;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_taskprocessor_listener *listener;</span><br><span> struct ast_taskprocessor *tps;</span><br><span> </span><br><span> ser = serializer_create(pool, shutdown_group);</span><br><span>@@ -1405,21 +1406,11 @@</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- listener = ast_taskprocessor_listener_alloc(&serializer_tps_listener_callbacks, ser);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!listener) {</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(ser, -1);</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- tps = ast_taskprocessor_create_with_listener(name, listener);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!tps) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* ser ref transferred to listener but not cleaned without tps */</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(ser, -1);</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (shutdown_group) {</span><br><span style="color: hsl(120, 100%, 40%);">+ tps = ast_taskprocessor_create_with_listener(name, &serializer_tps_listener_callbacks, ser);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tps && shutdown_group) {</span><br><span> serializer_shutdown_group_inc(shutdown_group);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(listener, -1);</span><br><span> return tps;</span><br><span> }</span><br><span> </span><br><span>diff --git a/tests/test_taskprocessor.c b/tests/test_taskprocessor.c</span><br><span>index 6428746..eaee0dd 100644</span><br><span>--- a/tests/test_taskprocessor.c</span><br><span>+++ b/tests/test_taskprocessor.c</span><br><span>@@ -309,7 +309,7 @@</span><br><span> /*!</span><br><span> * \brief test taskprocessor listener's start callback</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">-static int test_start(struct ast_taskprocessor_listener *listener)</span><br><span style="color: hsl(120, 100%, 40%);">+static int test_start(struct ast_taskprocessor *tps)</span><br><span> {</span><br><span> return 0;</span><br><span> }</span><br><span>@@ -319,9 +319,9 @@</span><br><span> *</span><br><span> * Adjusts private data's stats as indicated by the parameters.</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">-static void test_task_pushed(struct ast_taskprocessor_listener *listener, int was_empty)</span><br><span style="color: hsl(120, 100%, 40%);">+static void test_task_pushed(struct ast_taskprocessor *tps, int was_empty)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct test_listener_pvt *pvt = ast_taskprocessor_listener_get_user_data(listener);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct test_listener_pvt *pvt = ast_taskprocessor_get_user_data(tps);</span><br><span> ++pvt->num_pushed;</span><br><span> if (was_empty) {</span><br><span> ++pvt->num_was_empty;</span><br><span>@@ -331,22 +331,22 @@</span><br><span> /*!</span><br><span> * \brief test taskprocessor listener's emptied callback.</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">-static void test_emptied(struct ast_taskprocessor_listener *listener)</span><br><span style="color: hsl(120, 100%, 40%);">+static void test_emptied(struct ast_taskprocessor *tps)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct test_listener_pvt *pvt = ast_taskprocessor_listener_get_user_data(listener);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct test_listener_pvt *pvt = ast_taskprocessor_get_user_data(tps);</span><br><span> ++pvt->num_emptied;</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span> * \brief test taskprocessor listener's shutdown callback.</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">-static void test_shutdown(struct ast_taskprocessor_listener *listener)</span><br><span style="color: hsl(120, 100%, 40%);">+static void test_shutdown(struct ast_taskprocessor *tps)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct test_listener_pvt *pvt = ast_taskprocessor_listener_get_user_data(listener);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct test_listener_pvt *pvt = ast_taskprocessor_get_user_data(tps);</span><br><span> pvt->shutdown = 1;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static const struct ast_taskprocessor_listener_callbacks test_callbacks = {</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct ast_taskprocessor_callbacks test_callbacks = {</span><br><span> .start = test_start,</span><br><span> .task_pushed = test_task_pushed,</span><br><span> .emptied = test_emptied,</span><br><span>@@ -409,7 +409,6 @@</span><br><span> AST_TEST_DEFINE(taskprocessor_listener)</span><br><span> {</span><br><span> struct ast_taskprocessor *tps = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_taskprocessor_listener *listener = NULL;</span><br><span> struct test_listener_pvt *pvt = NULL;</span><br><span> enum ast_test_result_state res = AST_TEST_PASS;</span><br><span> </span><br><span>@@ -431,14 +430,7 @@</span><br><span> return AST_TEST_FAIL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- listener = ast_taskprocessor_listener_alloc(&test_callbacks, pvt);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!listener) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_test_status_update(test, "Unable to allocate test taskprocessor listener\n");</span><br><span style="color: hsl(0, 100%, 40%);">- res = AST_TEST_FAIL;</span><br><span style="color: hsl(0, 100%, 40%);">- goto test_exit;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- tps = ast_taskprocessor_create_with_listener("test_listener", listener);</span><br><span style="color: hsl(120, 100%, 40%);">+ tps = ast_taskprocessor_create_with_listener("test_listener", &test_callbacks, pvt);</span><br><span> if (!tps) {</span><br><span> ast_test_status_update(test, "Unable to allocate test taskprocessor\n");</span><br><span> res = AST_TEST_FAIL;</span><br><span>@@ -489,7 +481,6 @@</span><br><span> }</span><br><span> </span><br><span> test_exit:</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_cleanup(listener);</span><br><span> /* This is safe even if tps is NULL */</span><br><span> ast_taskprocessor_unreference(tps);</span><br><span> ast_free(pvt);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/10619">change 10619</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/10619"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I105ad352cad14638009fac7bf1faab8580f1458e </div>
<div style="display:none"> Gerrit-Change-Number: 10619 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Corey Farrell <git@cfware.com> </div>