Asterisk - The Open Source Telephony Project GIT-master-77d630f
taskpool.h
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2025, Sangoma Technologies Corporation
5 *
6 * Joshua C. Colp <jcolp@sangoma.com>
7 *
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.
13 *
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.
17 */
18
19/*! \file
20 * \ref Taskpool
21 *
22 * \page Taskpool API providing queued task execution across threads.
23
24The taskpool API is a specialized API for the queueing of tasks
25in a synchronous or asynchronous manner, to be executed across
26a pool of threads. For cases where serialization is needed a
27serializer API is also provided ensuring that tasks queued to
28the serializer are executed in a serialized fashion within the
29taskpool.
30
31On creation of a taskpool various options can be set and used to
32control the operation of the pool. This includes how many taskprocessors
33are present, whether the pool can grow, whether the pool can shrink,
34and how long idle taskprocessors should exist before being terminated.
35This provides flexibility based on the specific needs of the user of
36the taskpool and the environment.
37
38The queueing of tasks to the taskpool is done using a selector. The
39selector examines the available taskprocessors and decides which one
40to queue the task to. This operation can also examine the state of
41the pool to see if it needs to grow and if enabled and possible does so.
42
43The taskpool API is preferred for many cases over the use of the
44threadpool due to the far lower overhead involved. Taskpools require
45no additional thread or task queue for management of the pool itself and
46the act of queueing tasks, the most common operation, is written to be as
47simple and minimal as possible. Threadpools are best used for long
48running tasks and operations.
49
50*/
51
52#ifndef _ASTERISK_TASKPOOL_H
53#define _ASTERISK_TASKPOOL_H
54
55struct ast_taskpool;
58
59/*!
60 * \brief Selectors for choosing which taskprocessor in a pool to use
61 */
63 AST_TASKPOOL_SELECTOR_DEFAULT = 0, /* The selector that is generally the best for most use cases */
64 AST_TASKPOOL_SELECTOR_LEAST_FULL, /* Select the least full taskprocessor */
65 AST_TASKPOOL_SELECTOR_SEQUENTIAL, /* Select taskprocessors in a sequential manner */
66};
67
69#define AST_TASKPOOL_OPTIONS_VERSION 1
70 /*! Version of taskpool options in use */
72 /*!
73 * \brief The selector to use for choosing a taskprocessor
74 */
76 /*!
77 * \brief Time limit in seconds for idle dynamic taskprocessors
78 *
79 * A time of 0 or less will mean no timeout.
80 */
82 /*!
83 * \brief Number of taskprocessors to increment the pool by
84 */
86 /*!
87 * \brief Number of taskprocessors that will always exist
88 *
89 * Zero is a valid value if the taskpool will never have taskprocessors
90 * that always exist, allowing the pool to drop to zero if not used.
91 */
93 /*!
94 * \brief Number of taskprocessors the pool will start with
95 *
96 * Zero is a valid value if the taskpool should start
97 * without any taskprocessors allocated.
98 *
99 * \note This must be equal to or greater than the minimum_size,
100 * otherwise the taskpool will adjust this to the minimum_size.
101 */
103 /*!
104 * \brief Maximum number of taskprocessors a pool may have
105 *
106 * When the taskpool's size increases, it can never increase
107 * beyond this number of taskprocessors.
108 *
109 * Zero is a valid value if the taskpool does not have a
110 * maximum size for taskprocessors.
111 *
112 * \note This must be equal to or greater than the initial_size,
113 * otherwise the taskpool will adjust this to the initial_size.
114 */
116 /*!
117 * \brief The threshold for when to grow the pool
118 *
119 * This is the number of tasks that must be in queue before the pool will grow.
120 *
121 * \note If not specified a default of the 50% of the high water threshold defined
122 * in taskprocessor.h will be used.
123 */
125 /*!
126 * \brief Function to call when a taskprocessor starts
127 *
128 * This is useful if there is something common that all
129 * taskprocessors in a taskpool need to do when they start.
130 */
131 void (*thread_start)(void);
132 /*!
133 * \brief Function to call when a taskprocessor ends
134 *
135 * This is useful if there is common cleanup to execute when
136 * a taskprocessor completes
137 */
138 void (*thread_end)(void);
139};
140
141/*!
142 * \brief Create a new taskpool
143 * \since 23.1.0
144 * \since 22.7.0
145 * \since 20.17.0
146 *
147 * This function creates a taskpool. Tasks may be pushed onto this task pool
148 * and will be automatically acted upon by taskprocessors within the pool.
149 *
150 * Only a single taskpool with a given name may exist. This function will fail
151 * if a taskpool with the given name already exists.
152 *
153 * \param name The unique name for the taskpool
154 * \param options The behavioral options for this taskpool
155 * \retval NULL Failed to create the taskpool
156 * \retval non-NULL The newly-created taskpool
157 *
158 * \note The \ref ast_taskpool_shutdown function must be called to shut down the
159 * taskpool and clean up underlying resources fully.
160 */
161struct ast_taskpool *ast_taskpool_create(const char *name,
162 const struct ast_taskpool_options *options);
163
164/*!
165 * \brief Get the current number of taskprocessors in the taskpool
166 * \since 23.1.0
167 * \since 22.7.0
168 * \since 20.17.0
169 *
170 * \param pool The taskpool to query
171 * \retval The number of taskprocessors in the taskpool
172 */
174
175/*!
176 * \brief Get the current number of queued tasks in the taskpool
177 * \since 23.1.0
178 * \since 22.7.0
179 * \since 20.17.0
180 *
181 * \param pool The taskpool to query
182 * \retval The number of queued tasks in the taskpool
183 */
184long ast_taskpool_queue_size(struct ast_taskpool *pool);
185
186/*!
187 * \brief Push a task to the taskpool
188 * \since 23.1.0
189 * \since 22.7.0
190 * \since 20.17.0
191 *
192 * Tasks pushed into the taskpool will be automatically taken by
193 * one of the taskprocessors within
194 * \param pool The taskpool to add the task to
195 * \param task The task to add
196 * \param data The parameter for the task
197 * \retval 0 success
198 * \retval -1 failure
199 */
200int ast_taskpool_push(struct ast_taskpool *pool, int (*task)(void *data), void *data)
202
203/*!
204 * \brief Push a task to the taskpool, and wait for completion
205 * \since 23.1.0
206 * \since 22.7.0
207 * \since 20.17.0
208 *
209 * Tasks pushed into the taskpool will be automatically taken by
210 * one of the taskprocessors within
211 * \param pool The taskpool to add the task to
212 * \param task The task to add
213 * \param data The parameter for the task
214 * \retval 0 success
215 * \retval -1 failure
216 */
217int ast_taskpool_push_wait(struct ast_taskpool *pool, int (*task)(void *data), void *data)
219
220/*!
221 * \brief Shut down a taskpool and remove the underlying taskprocessors
222 * \since 23.1.0
223 * \since 22.7.0
224 * \since 20.17.0
225 *
226 * \param pool The pool to shut down
227 *
228 * \note This will decrement the reference to the pool
229 */
230void ast_taskpool_shutdown(struct ast_taskpool *pool);
231
232/*!
233 * \brief Get the taskpool serializer currently associated with this thread.
234 *
235 * \note The returned pointer is valid while the serializer
236 * thread is running.
237 *
238 * \note Use ao2_ref() on serializer if you are going to keep it
239 * for another thread. To unref it you must then use
240 * ast_taskprocessor_unreference().
241 *
242 * \retval serializer on success.
243 * \retval NULL on error or no serializer associated with the thread.
244 */
246
247/*!
248 * \brief Serialized execution of tasks within a \ref ast_taskpool.
249 * \since 23.1.0
250 * \since 22.7.0
251 * \since 20.17.0
252 *
253 * A \ref ast_taskprocessor with the same contract as a default taskprocessor
254 * (tasks execute serially) except instead of executing out of a dedicated
255 * thread, execution occurs in a taskprocessor from a \ref ast_taskpool.
256 *
257 * While it guarantees that each task will complete before executing the next,
258 * there is no guarantee as to which thread from the \c pool individual tasks
259 * will execute. This normally only matters if your code relies on thread
260 * specific information, such as thread locals.
261 *
262 * Use ast_taskprocessor_unreference() to dispose of the returned \ref
263 * ast_taskprocessor.
264 *
265 * Only a single taskprocessor with a given name may exist. This function will fail
266 * if a taskprocessor with the given name already exists.
267 *
268 * \param name Name of the serializer. (must be unique)
269 * \param pool \ref ast_taskpool for execution.
270 *
271 * \return \ref ast_taskprocessor for enqueuing work.
272 * \retval NULL on error.
273 */
274struct ast_taskprocessor *ast_taskpool_serializer(const char *name, struct ast_taskpool *pool);
275
276/*!
277 * \brief Serialized execution of tasks within a \ref ast_taskpool.
278 * \since 23.1.0
279 * \since 22.7.0
280 * \since 20.17.0
281 *
282 * A \ref ast_taskprocessor with the same contract as a default taskprocessor
283 * (tasks execute serially) except instead of executing out of a dedicated
284 * thread, execution occurs in a taskprocessor from a \ref ast_taskpool.
285 *
286 * While it guarantees that each task will complete before executing the next,
287 * there is no guarantee as to which thread from the \c pool individual tasks
288 * will execute. This normally only matters if your code relies on thread
289 * specific information, such as thread locals.
290 *
291 * Use ast_taskprocessor_unreference() to dispose of the returned \ref
292 * ast_taskprocessor.
293 *
294 * Only a single taskprocessor with a given name may exist. This function will fail
295 * if a taskprocessor with the given name already exists.
296 *
297 * \param name Name of the serializer. (must be unique)
298 * \param pool \ref ast_taskpool for execution.
299 * \param shutdown_group Group shutdown controller. (NULL if no group association)
300 *
301 * \return \ref ast_taskprocessor for enqueuing work.
302 * \retval NULL on error.
303 */
306
307/*!
308 * \brief Push a task to a serializer, and wait for completion
309 * \since 23.1.0
310 * \since 22.7.0
311 * \since 20.17.0
312 *
313 * \param serializer The serializer to add the task to
314 * \param task The task to add
315 * \param data The parameter for the task
316 * \retval 0 success
317 * \retval -1 failure
318 */
319int ast_taskpool_serializer_push_wait(struct ast_taskprocessor *serializer, int (*task)(void *data), void *data);
320
321#endif /* ASTERISK_TASKPOOL_H */
#define attribute_warn_unused_result
Definition: compiler.h:71
static const char name[]
Definition: format_mp3.c:68
static struct ast_serializer_shutdown_group * shutdown_group
Shutdown group for options serializers.
void(* thread_start)(void)
Function to call when a taskprocessor starts.
Definition: taskpool.h:131
int idle_timeout
Time limit in seconds for idle dynamic taskprocessors.
Definition: taskpool.h:81
enum ast_taskpool_selector selector
The selector to use for choosing a taskprocessor.
Definition: taskpool.h:75
int max_size
Maximum number of taskprocessors a pool may have.
Definition: taskpool.h:115
void(* thread_end)(void)
Function to call when a taskprocessor ends.
Definition: taskpool.h:138
int auto_increment
Number of taskprocessors to increment the pool by.
Definition: taskpool.h:85
int growth_threshold
The threshold for when to grow the pool.
Definition: taskpool.h:124
int minimum_size
Number of taskprocessors that will always exist.
Definition: taskpool.h:92
int initial_size
Number of taskprocessors the pool will start with.
Definition: taskpool.h:102
An opaque taskpool structure.
Definition: taskpool.c:62
A ast_taskprocessor structure is a singleton by name.
Definition: taskprocessor.c:69
size_t ast_taskpool_taskprocessors_count(struct ast_taskpool *pool)
Get the current number of taskprocessors in the taskpool.
Definition: taskpool.c:451
struct ast_taskprocessor * ast_taskpool_serializer(const char *name, struct ast_taskpool *pool)
Serialized execution of tasks within a ast_taskpool.
Definition: taskpool.c:819
void ast_taskpool_shutdown(struct ast_taskpool *pool)
Shut down a taskpool and remove the underlying taskprocessors.
Definition: taskpool.c:653
struct ast_taskprocessor * ast_taskpool_serializer_get_current(void)
Get the taskpool serializer currently associated with this thread.
Definition: taskpool.c:784
struct ast_taskprocessor * ast_taskpool_serializer_group(const char *name, struct ast_taskpool *pool, struct ast_serializer_shutdown_group *shutdown_group)
Serialized execution of tasks within a ast_taskpool.
Definition: taskpool.c:789
int ast_taskpool_push(struct ast_taskpool *pool, int(*task)(void *data), void *data) attribute_warn_unused_result
Push a task to the taskpool.
Definition: taskpool.c:522
ast_taskpool_selector
Selectors for choosing which taskprocessor in a pool to use.
Definition: taskpool.h:62
@ AST_TASKPOOL_SELECTOR_SEQUENTIAL
Definition: taskpool.h:65
@ AST_TASKPOOL_SELECTOR_LEAST_FULL
Definition: taskpool.h:64
@ AST_TASKPOOL_SELECTOR_DEFAULT
Definition: taskpool.h:63
int ast_taskpool_serializer_push_wait(struct ast_taskprocessor *serializer, int(*task)(void *data), void *data)
Push a task to a serializer, and wait for completion.
Definition: taskpool.c:832
struct ast_taskpool * ast_taskpool_create(const char *name, const struct ast_taskpool_options *options)
Create a new taskpool.
Definition: taskpool.c:324
long ast_taskpool_queue_size(struct ast_taskpool *pool)
Get the current number of queued tasks in the taskpool.
Definition: taskpool.c:464
int ast_taskpool_push_wait(struct ast_taskpool *pool, int(*task)(void *data), void *data) attribute_warn_unused_result
Push a task to the taskpool, and wait for completion.
Definition: taskpool.c:623
static struct test_options options
static int task(void *data)
Queued task for baseline test.