struct ast_threadpool_listener_callbacks {
/*!
- * \brief Allocate the listener's private data
- *
- * It is not necessary to assign the private data to the listener.
- * \param listener The listener the private data will belong to
- * \retval NULL Failure to allocate private data
- * \retval non-NULL The newly allocated private data
- */
- void *(*alloc)(struct ast_threadpool_listener *listener);
- /*!
* \brief Indicates that the state of threads in the pool has changed
*
+ * \param pool The pool whose state has changed
* \param listener The threadpool listener
* \param active_threads The number of active threads in the pool
* \param idle_threads The number of idle threads in the pool
/*!
* \brief Indicates that a task was pushed to the threadpool
*
+ * \param pool The pool that had a task pushed
* \param listener The threadpool listener
* \param was_empty Indicates whether there were any tasks prior to adding the new one.
*/
/*!
* \brief Indicates the threadpool's taskprocessor has become empty
*
+ * \param pool The pool that has become empty
* \param listener The threadpool's listener
*/
void (*emptied)(struct ast_threadpool *pool, struct ast_threadpool_listener *listener);
/*!
- * \brief Free the listener's private data
- * \param private_data The private data to destroy
+ * \brief The threadpool is shutting down
+ *
+ * This would be an opportune time to free the listener's user data
+ * if one wishes. However, it is acceptable to not do so if the user data
+ * should persist beyond the lifetime of the pool.
+ *
+ * \param listener The threadpool's listener
*/
- void (*destroy)(void *private_data);
+ void (*shutdown)(struct ast_threadpool_listener *listener);
};
/*!
/*! Callbacks called by the threadpool */
const struct ast_threadpool_listener_callbacks *callbacks;
/*! User data for the listener */
- void *private_data;
+ void *user_data;
};
struct ast_threadpool_options {
* listener.
*
* \param callbacks Listener callbacks to assign to the listener
+ * \param user_data User data to be stored in the threadpool listener
* \retval NULL Failed to allocate the listener
* \retval non-NULL The newly-created threadpool listener
*/
struct ast_threadpool_listener *ast_threadpool_listener_alloc(
- const struct ast_threadpool_listener_callbacks *callbacks);
+ const struct ast_threadpool_listener_callbacks *callbacks, void *user_data);
/*!
* \brief Create a new threadpool
ast_cond_t cond;
};
-static void *test_alloc(struct ast_threadpool_listener *listener)
+static struct test_listener_data *test_alloc(void)
{
struct test_listener_data *tld = ast_calloc(1, sizeof(*tld));
if (!tld) {
int active_threads,
int idle_threads)
{
- struct test_listener_data *tld = listener->private_data;
+ struct test_listener_data *tld = listener->user_data;
SCOPED_MUTEX(lock, &tld->lock);
tld->num_active = active_threads;
tld->num_idle = idle_threads;
struct ast_threadpool_listener *listener,
int was_empty)
{
- struct test_listener_data *tld = listener->private_data;
+ struct test_listener_data *tld = listener->user_data;
SCOPED_MUTEX(lock, &tld->lock);
tld->task_pushed = 1;
++tld->num_tasks;
static void test_emptied(struct ast_threadpool *pool,
struct ast_threadpool_listener *listener)
{
- struct test_listener_data *tld = listener->private_data;
+ struct test_listener_data *tld = listener->user_data;
SCOPED_MUTEX(lock, &tld->lock);
tld->empty_notice = 1;
ast_cond_signal(&tld->cond);
}
-static void test_destroy(void *private_data)
+static void test_shutdown(struct ast_threadpool_listener *listener)
{
- struct test_listener_data *tld = private_data;
+ struct test_listener_data *tld = listener->user_data;
ast_cond_destroy(&tld->cond);
ast_mutex_destroy(&tld->lock);
- ast_free(tld);
}
static const struct ast_threadpool_listener_callbacks test_callbacks = {
- .alloc = test_alloc,
.state_changed = test_state_changed,
.task_pushed = test_task_pushed,
.emptied = test_emptied,
- .destroy = test_destroy,
+ .shutdown = test_shutdown,
};
struct simple_task_data {
static void wait_for_task_pushed(struct ast_threadpool_listener *listener)
{
- struct test_listener_data *tld = listener->private_data;
+ struct test_listener_data *tld = listener->user_data;
struct timeval start = ast_tvnow();
struct timespec end = {
.tv_sec = start.tv_sec + 5,
int num_idle,
int empty_notice)
{
- struct test_listener_data *tld = listener->private_data;
+ struct test_listener_data *tld = listener->user_data;
enum ast_test_result_state res = AST_TEST_PASS;
if (tld->task_pushed != task_pushed) {
struct ast_threadpool *pool = NULL;
struct ast_threadpool_listener *listener = NULL;
struct simple_task_data *std = NULL;
+ struct test_listener_data *tld = NULL;
enum ast_test_result_state res = AST_TEST_FAIL;
struct ast_threadpool_options options = {
.version = AST_THREADPOOL_OPTIONS_VERSION,
case TEST_EXECUTE:
break;
}
+ tld = test_alloc();
+ if (!tld) {
+ return AST_TEST_FAIL;
+ }
- listener = ast_threadpool_listener_alloc(&test_callbacks);
+ listener = ast_threadpool_listener_alloc(&test_callbacks, tld);
if (!listener) {
- return AST_TEST_FAIL;
+ goto end;
}
pool = ast_threadpool_create(info->name, listener, 0, &options);
}
ao2_cleanup(listener);
ast_free(std);
+ ast_free(tld);
return res;
}
break;
}
- listener = ast_threadpool_listener_alloc(&test_callbacks);
- if (!listener) {
+ tld = test_alloc();
+ if (!tld) {
return AST_TEST_FAIL;
}
- tld = listener->private_data;
+
+ listener = ast_threadpool_listener_alloc(&test_callbacks, tld);
+ if (!listener) {
+ goto end;
+ }
pool = ast_threadpool_create(info->name, listener, 3, &options);
if (!pool) {
ast_threadpool_shutdown(pool);
}
ao2_cleanup(listener);
+ ast_free(tld);
return res;
}
break;
}
- listener = ast_threadpool_listener_alloc(&test_callbacks);
- if (!listener) {
+ tld = test_alloc();
+ if (!tld) {
return AST_TEST_FAIL;
}
- tld = listener->private_data;
+
+ listener = ast_threadpool_listener_alloc(&test_callbacks, tld);
+ if (!listener) {
+ goto end;
+ }
pool = ast_threadpool_create(info->name, listener, 0, &options);
if (!pool) {
ast_threadpool_shutdown(pool);
}
ao2_cleanup(listener);
+ ast_free(tld);
return res;
}
break;
}
- listener = ast_threadpool_listener_alloc(&test_callbacks);
- if (!listener) {
+ tld = test_alloc();
+ if (!tld) {
return AST_TEST_FAIL;
}
- tld = listener->private_data;
+
+ listener = ast_threadpool_listener_alloc(&test_callbacks, tld);
+ if (!listener) {
+ goto end;
+ }
pool = ast_threadpool_create(info->name, listener, 0, &options);
if (!pool) {
ast_threadpool_shutdown(pool);
}
ao2_cleanup(listener);
+ ast_free(tld);
return res;
}
break;
}
- listener = ast_threadpool_listener_alloc(&test_callbacks);
- if (!listener) {
+ tld = test_alloc();
+ if (!tld) {
return AST_TEST_FAIL;
}
- tld = listener->private_data;
+
+ listener = ast_threadpool_listener_alloc(&test_callbacks, tld);
+ if (!listener) {
+ goto end;
+ }
pool = ast_threadpool_create(info->name, listener, 0, &options);
if (!pool) {
ast_threadpool_shutdown(pool);
}
ao2_cleanup(listener);
+ ast_free(tld);
return res;
}
break;
}
- listener = ast_threadpool_listener_alloc(&test_callbacks);
- if (!listener) {
+ tld = test_alloc();
+ if (!tld) {
return AST_TEST_FAIL;
}
- tld = listener->private_data;
+
+ listener = ast_threadpool_listener_alloc(&test_callbacks, tld);
+ if (!listener) {
+ goto end;
+ }
pool = ast_threadpool_create(info->name, listener, 0, &options);
if (!pool) {
}
ao2_cleanup(listener);
ast_free(std);
+ ast_free(tld);
return res;
}
break;
}
- listener = ast_threadpool_listener_alloc(&test_callbacks);
- if (!listener) {
+ tld = test_alloc();
+ if (!tld) {
return AST_TEST_FAIL;
}
- tld = listener->private_data;
+
+ listener = ast_threadpool_listener_alloc(&test_callbacks, tld);
+ if (!listener) {
+ goto end;
+ }
pool = ast_threadpool_create(info->name, listener, 0, &options);
if (!pool) {
}
ao2_cleanup(listener);
ast_free(std);
+ ast_free(tld);
return res;
}
break;
}
- listener = ast_threadpool_listener_alloc(&test_callbacks);
- if (!listener) {
+ tld = test_alloc();
+ if (!tld) {
return AST_TEST_FAIL;
}
- tld = listener->private_data;
+
+ listener = ast_threadpool_listener_alloc(&test_callbacks, tld);
+ if (!listener) {
+ goto end;
+ }
pool = ast_threadpool_create(info->name, listener, 0, &options);
if (!pool) {
ast_free(std1);
ast_free(std2);
ast_free(std3);
+ ast_free(tld);
return res;
}
break;
}
- listener = ast_threadpool_listener_alloc(&test_callbacks);
- if (!listener) {
+ tld = test_alloc();
+ if (!tld) {
return AST_TEST_FAIL;
}
- tld = listener->private_data;
+
+ listener = ast_threadpool_listener_alloc(&test_callbacks, tld);
+ if (!listener) {
+ goto end;
+ }
pool = ast_threadpool_create(info->name, listener, 0, &options);
if (!pool) {
ast_free(std2);
ast_free(std3);
ast_free(std4);
+ ast_free(tld);
return res;
}
break;
}
- listener = ast_threadpool_listener_alloc(&test_callbacks);
- if (!listener) {
+ tld = test_alloc();
+ if (!tld) {
return AST_TEST_FAIL;
}
- tld = listener->private_data;
+
+ listener = ast_threadpool_listener_alloc(&test_callbacks, tld);
+ if (!listener) {
+ goto end;
+ }
pool = ast_threadpool_create(info->name, listener, 0, &options);
if (!pool) {
ao2_cleanup(listener);
ast_free(std1);
ast_free(std2);
+ ast_free(tld);
return res;
}
break;
}
- listener = ast_threadpool_listener_alloc(&test_callbacks);
- if (!listener) {
+ tld = test_alloc();
+ if (!tld) {
return AST_TEST_FAIL;
}
- tld = listener->private_data;
+
+ listener = ast_threadpool_listener_alloc(&test_callbacks, tld);
+ if (!listener) {
+ goto end;
+ }
pool = ast_threadpool_create(info->name, listener, 0, &options);
if (!pool) {
ao2_cleanup(listener);
ast_free(ctd1);
ast_free(ctd2);
+ ast_free(tld);
return res;
}
break;
}
- listener = ast_threadpool_listener_alloc(&test_callbacks);
- if (!listener) {
+ tld = test_alloc();
+ if (!tld) {
return AST_TEST_FAIL;
}
- tld = listener->private_data;
+
+ listener = ast_threadpool_listener_alloc(&test_callbacks, tld);
+ if (!listener) {
+ goto end;
+ }
pool = ast_threadpool_create(info->name, listener, 0, &options);
if (!pool) {
ao2_cleanup(listener);
ast_free(ctd1);
ast_free(ctd2);
+ ast_free(tld);
return res;
}