2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2012, Digium, Inc.
6 * Mark Michelson <mmmichelson@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
22 #include "asterisk/threadpool.h"
23 #include "asterisk/taskprocessor.h"
25 struct ast_threadpool;
33 struct worker_thread {
37 struct ast_threadpool *pool;
38 AST_LIST_ENTRY(struct worker_thread) next;
40 enum worker_state state;
43 static int worker_idle(struct worker_thread *worker)
45 SCOPED_MUTEX(lock, &worker->lock);
46 if (worker->state != ALIVE) {
49 threadpool_active_thread_idle(worker->pool, worker);
50 while (!worker->wake_up) {
51 ast_cond_wait(&worker->cond, lock);
53 worker->wake_up = false;
54 return worker->state == ALIVE;
57 static int worker_active(struct worker_thread *worker)
61 if (threadpool_execute(worker->pool)) {
62 alive = worker_idle(worker);
66 /* Reaching this portion means the thread is
67 * on death's door. It may have been killed while
68 * it was idle, in which case it can just die
69 * peacefully. If it's a zombie, though, then
70 * it needs to let the pool know so
71 * that the thread can be removed from the
72 * list of zombie threads.
74 if (worker->state == ZOMBIE) {
75 threadpool_zombie_thread_dead(worker->pool, worker);
81 struct ast_threadpool {
82 struct ast_threadpool_listener *threadpool_listener;
88 static void *threadpool_tps_listener_alloc(struct ast_taskprocessor_listener *listener)
90 RAII_VAR(ast_threadpool *, threadpool,
91 ao2_alloc(sizeof(*threadpool), threadpool_destroy), ao2_cleanup);
96 static void threadpool_tps_task_pushed(struct ast_taskprocessor_listener *listener)
101 static void threadpool_tps_emptied(struct ast_taskprocessor_listener *listener)
106 static void threadpool_tps_shutdown(struct ast_taskprocessor_listener *listener)
111 static void threadpool_tps_listener_destroy(struct ast_taskprocessor_listener *listener)
116 static struct ast_taskprocessor_listener_callbacks threadpool_tps_listener_callbacks = {
117 .alloc = threadpool_tps_listener_alloc,
118 .task_pushed = threadpool_tps_task_pushed,
119 .emptied = threadpool_tps_emptied,
120 .shutdown = threadpool_tps_shutdown,
121 .destroy = threadpool_tps_listener_destroy,
125 * \brief Allocate the taskprocessor to be used for the threadpool
127 * We use a custom taskprocessor listener. We allocate our custom
128 * listener and then create a taskprocessor.
130 static struct ast_taskprocessor_listener *threadpool_tps_alloc(void)
132 RAII_VAR(struct threadpool_tps_listener *, tps_listener,
133 ast_taskprocessor_listener_alloc(&threadpool_tps_listener_callbacks),
140 return ast_taskprocessor_create_with_listener(tps_listener);
143 void ast_threadpool_set_size(struct ast_threadpool *pool, int size)
147 struct ast_threadpool *ast_threadpool_create(struct ast_threadpool_listener *listener, int initial_size)
149 struct ast_threadpool *pool;
150 RAII_VAR(ast_taskprocessor *, tps, threadpool_tps_alloc(), ast_taskprocessor_unreference);
156 pool = tps->listener->private_data;
158 ast_threadpool_set_size(pool, initial_size);