<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>