Asterisk - The Open Source Telephony Project GIT-master-4f2b068
Loading...
Searching...
No Matches
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
50Serializers created from a taskpool also have the ability to be suspended.
51When suspended no taskpool taskprocessor executes any tasks on the
52serializer resulting in the queue of tasks on the serializer growing. It
53is only when unsuspended that the serializer will once again have its queue
54of tasks processed. As a result it is important to suspend a serializer
55for the minimum amount of time necessary.
56
57*/
58
59#ifndef _ASTERISK_TASKPOOL_H
60#define _ASTERISK_TASKPOOL_H
61
62struct ast_taskpool;
65
66/*!
67 * \brief Selectors for choosing which taskprocessor in a pool to use
68 */
70 AST_TASKPOOL_SELECTOR_DEFAULT = 0, /* The selector that is generally the best for most use cases */
71 AST_TASKPOOL_SELECTOR_LEAST_FULL, /* Select the least full taskprocessor */
72 AST_TASKPOOL_SELECTOR_SEQUENTIAL, /* Select taskprocessors in a sequential manner */
73};
74
76#define AST_TASKPOOL_OPTIONS_VERSION 1
77 /*! Version of taskpool options in use */
79 /*!
80 * \brief The selector to use for choosing a taskprocessor
81 */
83 /*!
84 * \brief Time limit in seconds for idle dynamic taskprocessors
85 *
86 * A time of 0 or less will mean no timeout.
87 */
89 /*!
90 * \brief Number of taskprocessors to increment the pool by
91 */
93 /*!
94 * \brief Number of taskprocessors that will always exist
95 *
96 * Zero is a valid value if the taskpool will never have taskprocessors
97 * that always exist, allowing the pool to drop to zero if not used.
98 */
100 /*!
101 * \brief Number of taskprocessors the pool will start with
102 *
103 * Zero is a valid value if the taskpool should start
104 * without any taskprocessors allocated.
105 *
106 * \note This must be equal to or greater than the minimum_size,
107 * otherwise the taskpool will adjust this to the minimum_size.
108 */
110 /*!
111 * \brief Maximum number of taskprocessors a pool may have
112 *
113 * When the taskpool's size increases, it can never increase
114 * beyond this number of taskprocessors.
115 *
116 * Zero is a valid value if the taskpool does not have a
117 * maximum size for taskprocessors.
118 *
119 * \note This must be equal to or greater than the initial_size,
120 * otherwise the taskpool will adjust this to the initial_size.
121 */
123 /*!
124 * \brief The threshold for when to grow the pool
125 *
126 * This is the number of tasks that must be in queue before the pool will grow.
127 *
128 * \note If not specified a default of the 50% of the high water threshold defined
129 * in taskprocessor.h will be used.
130 */
132 /*!
133 * \brief Function to call when a taskprocessor starts
134 *
135 * This is useful if there is something common that all
136 * taskprocessors in a taskpool need to do when they start.
137 */
138 void (*thread_start)(void);
139 /*!
140 * \brief Function to call when a taskprocessor ends
141 *
142 * This is useful if there is common cleanup to execute when
143 * a taskprocessor completes
144 */
145 void (*thread_end)(void);
146};
147
148/*!
149 * \brief Create a new taskpool
150 * \since 23.1.0
151 * \since 22.7.0
152 * \since 20.17.0
153 *
154 * This function creates a taskpool. Tasks may be pushed onto this task pool
155 * and will be automatically acted upon by taskprocessors within the pool.
156 *
157 * Only a single taskpool with a given name may exist. This function will fail
158 * if a taskpool with the given name already exists.
159 *
160 * \param name The unique name for the taskpool
161 * \param options The behavioral options for this taskpool
162 * \retval NULL Failed to create the taskpool
163 * \retval non-NULL The newly-created taskpool
164 *
165 * \note The \ref ast_taskpool_shutdown function must be called to shut down the
166 * taskpool and clean up underlying resources fully.
167 */
168struct ast_taskpool *ast_taskpool_create(const char *name,
169 const struct ast_taskpool_options *options);
170
171/*!
172 * \brief Get the current number of taskprocessors in the taskpool
173 * \since 23.1.0
174 * \since 22.7.0
175 * \since 20.17.0
176 *
177 * \param pool The taskpool to query
178 * \retval The number of taskprocessors in the taskpool
179 */
181
182/*!
183 * \brief Get the current number of queued tasks in the taskpool
184 * \since 23.1.0
185 * \since 22.7.0
186 * \since 20.17.0
187 *
188 * \param pool The taskpool to query
189 * \retval The number of queued tasks in the taskpool
190 */
191long ast_taskpool_queue_size(struct ast_taskpool *pool);
192
193/*!
194 * \brief Push a task to the taskpool
195 * \since 23.1.0
196 * \since 22.7.0
197 * \since 20.17.0
198 *
199 * Tasks pushed into the taskpool will be automatically taken by
200 * one of the taskprocessors within
201 * \param pool The taskpool to add the task to
202 * \param task The task to add
203 * \param data The parameter for the task
204 * \retval 0 success
205 * \retval -1 failure
206 */
207int __ast_taskpool_push(struct ast_taskpool *pool, int (*task)(void *data), void *data,
208 const char *file, int line, const char *function)
210#define ast_taskpool_push(pool, task, data) \
211 __ast_taskpool_push(pool, task, data, __FILE__, __LINE__, __PRETTY_FUNCTION__)
212
213/*!
214 * \brief Push a task to the taskpool, and wait for completion
215 * \since 23.1.0
216 * \since 22.7.0
217 * \since 20.17.0
218 *
219 * Tasks pushed into the taskpool will be automatically taken by
220 * one of the taskprocessors within
221 * \param pool The taskpool to add the task to
222 * \param task The task to add
223 * \param data The parameter for the task
224 * \retval 0 success
225 * \retval -1 failure
226 */
227int __ast_taskpool_push_wait(struct ast_taskpool *pool, int (*task)(void *data), void *data,
228 const char *file, int line, const char *function)
230#define ast_taskpool_push_wait(pool, task, data) \
231 __ast_taskpool_push_wait(pool, task, data, __FILE__, __LINE__, __PRETTY_FUNCTION__)
232
233/*!
234 * \brief Shut down a taskpool and remove the underlying taskprocessors
235 * \since 23.1.0
236 * \since 22.7.0
237 * \since 20.17.0
238 *
239 * \param pool The pool to shut down
240 *
241 * \note This will decrement the reference to the pool
242 */
243void ast_taskpool_shutdown(struct ast_taskpool *pool);
244
245/*!
246 * \brief Get the taskpool serializer currently associated with this thread.
247 *
248 * \note The returned pointer is valid while the serializer
249 * thread is running.
250 *
251 * \note Use ao2_ref() on serializer if you are going to keep it
252 * for another thread. To unref it you must then use
253 * ast_taskprocessor_unreference().
254 *
255 * \retval serializer on success.
256 * \retval NULL on error or no serializer associated with the thread.
257 */
259
260/*!
261 * \brief Serialized execution of tasks within a \ref ast_taskpool.
262 * \since 23.1.0
263 * \since 22.7.0
264 * \since 20.17.0
265 *
266 * A \ref ast_taskprocessor with the same contract as a default taskprocessor
267 * (tasks execute serially) except instead of executing out of a dedicated
268 * thread, execution occurs in a taskprocessor from a \ref ast_taskpool.
269 *
270 * While it guarantees that each task will complete before executing the next,
271 * there is no guarantee as to which thread from the \c pool individual tasks
272 * will execute. This normally only matters if your code relies on thread
273 * specific information, such as thread locals.
274 *
275 * Use ast_taskprocessor_unreference() to dispose of the returned \ref
276 * ast_taskprocessor.
277 *
278 * Only a single taskprocessor with a given name may exist. This function will fail
279 * if a taskprocessor with the given name already exists.
280 *
281 * \param name Name of the serializer. (must be unique)
282 * \param pool \ref ast_taskpool for execution.
283 *
284 * \return \ref ast_taskprocessor for enqueuing work.
285 * \retval NULL on error.
286 */
287struct ast_taskprocessor *ast_taskpool_serializer(const char *name, struct ast_taskpool *pool);
288
289/*!
290 * \brief Serialized execution of tasks within a \ref ast_taskpool.
291 * \since 23.1.0
292 * \since 22.7.0
293 * \since 20.17.0
294 *
295 * A \ref ast_taskprocessor with the same contract as a default taskprocessor
296 * (tasks execute serially) except instead of executing out of a dedicated
297 * thread, execution occurs in a taskprocessor from a \ref ast_taskpool.
298 *
299 * While it guarantees that each task will complete before executing the next,
300 * there is no guarantee as to which thread from the \c pool individual tasks
301 * will execute. This normally only matters if your code relies on thread
302 * specific information, such as thread locals.
303 *
304 * Use ast_taskprocessor_unreference() to dispose of the returned \ref
305 * ast_taskprocessor.
306 *
307 * Only a single taskprocessor with a given name may exist. This function will fail
308 * if a taskprocessor with the given name already exists.
309 *
310 * \param name Name of the serializer. (must be unique)
311 * \param pool \ref ast_taskpool for execution.
312 * \param shutdown_group Group shutdown controller. (NULL if no group association)
313 *
314 * \return \ref ast_taskprocessor for enqueuing work.
315 * \retval NULL on error.
316 */
319
320/*!
321 * \brief Push a task to a serializer, and wait for completion
322 * \since 23.1.0
323 * \since 22.7.0
324 * \since 20.17.0
325 *
326 * \param serializer The serializer to add the task to
327 * \param task The task to add
328 * \param data The parameter for the task
329 * \retval 0 success
330 * \retval -1 failure
331 */
332int __ast_taskpool_serializer_push_wait(struct ast_taskprocessor *serializer, int (*task)(void *data), void *data,
333 const char *file, int line, const char *function)
335#define ast_taskpool_serializer_push_wait(pool, task, data) \
336 __ast_taskpool_serializer_push_wait(pool, task, data, __FILE__, __LINE__, __PRETTY_FUNCTION__)
337
338/*!
339 * \brief Suspend a serializer, causing tasks to be queued until unsuspended
340 * \since 23.2.0
341 * \since 22.8.0
342 * \since 20.18.0
343 *
344 * \param serializer The serializer to suspend
345 * \retval 0 success
346 * \retval -1 failure
347 *
348 * \note May only be invoked from outside of the taskpool
349 */
351
352/*!
353 * \brief Unsuspend a serializer, causing tasks to be executed
354 * \since 23.2.0
355 * \since 22.8.0
356 * \since 20.18.0
357 *
358 * \param serializer The serializer to unsuspend
359 * \retval 0 success
360 * \retval -1 failure
361 *
362 * \note May only be invoked from outside of the taskpool
363 */
365
366#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:138
int idle_timeout
Time limit in seconds for idle dynamic taskprocessors.
Definition taskpool.h:88
enum ast_taskpool_selector selector
The selector to use for choosing a taskprocessor.
Definition taskpool.h:82
int max_size
Maximum number of taskprocessors a pool may have.
Definition taskpool.h:122
void(* thread_end)(void)
Function to call when a taskprocessor ends.
Definition taskpool.h:145
int auto_increment
Number of taskprocessors to increment the pool by.
Definition taskpool.h:92
int growth_threshold
The threshold for when to grow the pool.
Definition taskpool.h:131
int minimum_size
Number of taskprocessors that will always exist.
Definition taskpool.h:99
int initial_size
Number of taskprocessors the pool will start with.
Definition taskpool.h:109
An opaque taskpool structure.
Definition taskpool.c:62
A ast_taskprocessor structure is a singleton by name.
int __ast_taskpool_push_wait(struct ast_taskpool *pool, int(*task)(void *data), void *data, const char *file, int line, const char *function) attribute_warn_unused_result
Push a task to the taskpool, and wait for completion.
Definition taskpool.c:635
int __ast_taskpool_serializer_push_wait(struct ast_taskprocessor *serializer, int(*task)(void *data), void *data, const char *file, int line, const char *function) attribute_warn_unused_result
Push a task to a serializer, and wait for completion.
Definition taskpool.c:882
int ast_taskpool_serializer_unsuspend(struct ast_taskprocessor *serializer)
Unsuspend a serializer, causing tasks to be executed.
Definition taskpool.c:1050
size_t ast_taskpool_taskprocessors_count(struct ast_taskpool *pool)
Get the current number of taskprocessors in the taskpool.
Definition taskpool.c:451
int ast_taskpool_serializer_suspend(struct ast_taskprocessor *serializer)
Suspend a serializer, causing tasks to be queued until unsuspended.
Definition taskpool.c:1001
struct ast_taskprocessor * ast_taskpool_serializer(const char *name, struct ast_taskpool *pool)
Serialized execution of tasks within a ast_taskpool.
Definition taskpool.c:860
void ast_taskpool_shutdown(struct ast_taskpool *pool)
Shut down a taskpool and remove the underlying taskprocessors.
Definition taskpool.c:675
int __ast_taskpool_push(struct ast_taskpool *pool, int(*task)(void *data), void *data, const char *file, int line, const char *function) attribute_warn_unused_result
Push a task to the taskpool.
Definition taskpool.c:527
struct ast_taskprocessor * ast_taskpool_serializer_get_current(void)
Get the taskpool serializer currently associated with this thread.
Definition taskpool.c:825
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:830
ast_taskpool_selector
Selectors for choosing which taskprocessor in a pool to use.
Definition taskpool.h:69
@ AST_TASKPOOL_SELECTOR_SEQUENTIAL
Definition taskpool.h:72
@ AST_TASKPOOL_SELECTOR_LEAST_FULL
Definition taskpool.h:71
@ AST_TASKPOOL_SELECTOR_DEFAULT
Definition taskpool.h:70
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
static struct test_options options
static int task(void *data)
Queued task for baseline test.