15093175a9acd7271cdbb96257ebc46599ca5409
[asterisk/asterisk.git] / include / asterisk / threadpool.h
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2012-2013, Digium, Inc.
5  *
6  * Mark Michelson <mmmichelson@digium.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
20 #ifndef _ASTERISK_THREADPOOL_H
21 #define _ASTERISK_THREADPOOL_H
22
23 struct ast_threadpool;
24 struct ast_taskprocessor;
25 struct ast_threadpool_listener;
26
27 struct ast_threadpool_listener_callbacks {
28         /*!
29          * \brief Indicates that the state of threads in the pool has changed
30          *
31          * \param pool The pool whose state has changed
32          * \param listener The threadpool listener
33          * \param active_threads The number of active threads in the pool
34          * \param idle_threads The number of idle threads in the pool
35          */
36         void (*state_changed)(struct ast_threadpool *pool,
37                         struct ast_threadpool_listener *listener,
38                         int active_threads,
39                         int idle_threads);
40         /*!
41          * \brief Indicates that a task was pushed to the threadpool
42          *
43          * \param pool The pool that had a task pushed
44          * \param listener The threadpool listener
45          * \param was_empty Indicates whether there were any tasks prior to adding the new one.
46          */
47         void (*task_pushed)(struct ast_threadpool *pool,
48                         struct ast_threadpool_listener *listener,
49                         int was_empty);
50         /*!
51          * \brief Indicates the threadpool's taskprocessor has become empty
52          *
53          * \param pool The pool that has become empty
54          * \param listener The threadpool's listener
55          */
56         void (*emptied)(struct ast_threadpool *pool, struct ast_threadpool_listener *listener);
57
58         /*!
59          * \brief The threadpool is shutting down
60          *
61          * This would be an opportune time to free the listener's user data
62          * if one wishes. However, it is acceptable to not do so if the user data
63          * should persist beyond the lifetime of the pool.
64          *
65          * \param listener The threadpool's listener
66          */
67         void (*shutdown)(struct ast_threadpool_listener *listener);
68 };
69
70 struct ast_threadpool_options {
71 #define AST_THREADPOOL_OPTIONS_VERSION 1
72         /*! Version of threadpool options in use */
73         int version;
74         /*!
75          * \brief Time limit in seconds for idle threads
76          *
77          * A time of 0 or less will mean no timeout.
78          */
79         int idle_timeout;
80         /*!
81          * \brief Number of threads to increment pool by
82          *
83          * If a task is added into a pool and no idle thread is
84          * available to activate, then the pool can automatically
85          * grow by the given amount.
86          *
87          * Zero is a perfectly valid value to give here if you want
88          * to control threadpool growth yourself via your listener.
89          */
90         int auto_increment;
91         /*!
92          * \brief Number of threads the pool will start with
93          *
94          * When the threadpool is allocated, it will immediately size
95          * itself to have this number of threads in it.
96          *
97          * Zero is a valid value if the threadpool should start
98          * without any threads allocated.
99          */
100         int initial_size;
101         /*!
102          * \brief Maximum number of threads a pool may have
103          *
104          * When the threadpool's size increases, it can never increase
105          * beyond this number of threads.
106          */
107         int max_size;
108 };
109
110 /*!
111  * \brief Allocate a threadpool listener
112  *
113  * This function will call back into the alloc callback for the
114  * listener.
115  *
116  * \param callbacks Listener callbacks to assign to the listener
117  * \param user_data User data to be stored in the threadpool listener
118  * \retval NULL Failed to allocate the listener
119  * \retval non-NULL The newly-created threadpool listener
120  */
121 struct ast_threadpool_listener *ast_threadpool_listener_alloc(
122                 const struct ast_threadpool_listener_callbacks *callbacks, void *user_data);
123
124 /*!
125  * \brief Get the threadpool listener's user data
126  * \param listener The threadpool listener
127  * \return The user data
128  */
129 void *ast_threadpool_listener_get_user_data(const struct ast_threadpool_listener *listener);
130
131 /*!
132  * \brief Create a new threadpool
133  *
134  * This function creates a threadpool. Tasks may be pushed onto this thread pool
135  * in and will be automatically acted upon by threads within the pool.
136  *
137  * Only a single threadpool with a given name may exist. This function will fail
138  * if a threadpool with the given name already exists.
139  *
140  * \param name The unique name for the threadpool
141  * \param listener The listener the threadpool will notify of changes. Can be NULL.
142  * \param options The behavioral options for this threadpool
143  * \retval NULL Failed to create the threadpool
144  * \retval non-NULL The newly-created threadpool
145  */
146 struct ast_threadpool *ast_threadpool_create(const char *name,
147                 struct ast_threadpool_listener *listener,
148                 const struct ast_threadpool_options *options);
149
150 /*!
151  * \brief Set the number of threads for the thread pool
152  *
153  * This number may be more or less than the current number of
154  * threads in the threadpool.
155  *
156  * \param threadpool The threadpool to adjust
157  * \param size The new desired size of the threadpool
158  */
159 void ast_threadpool_set_size(struct ast_threadpool *threadpool, unsigned int size);
160
161 /*!
162  * \brief Push a task to the threadpool
163  *
164  * Tasks pushed into the threadpool will be automatically taken by
165  * one of the threads within
166  * \param pool The threadpool to add the task to
167  * \param task The task to add
168  * \param data The parameter for the task
169  * \retval 0 success
170  * \retval -1 failure
171  */
172 int ast_threadpool_push(struct ast_threadpool *pool, int (*task)(void *data), void *data);
173
174 /*!
175  * \brief Shut down a threadpool and destroy it
176  *
177  * \param pool The pool to shut down
178  */
179 void ast_threadpool_shutdown(struct ast_threadpool *pool);
180
181 /*!
182  * \brief Serialized execution of tasks within a \ref ast_threadpool.
183  *
184  * \since 12.0.0
185  *
186  * A \ref ast_taskprocessor with the same contract as a default taskprocessor
187  * (tasks execute serially) except instead of executing out of a dedicated
188  * thread, execution occurs in a thread from a \ref ast_threadpool. Think of it
189  * as a lightweight thread.
190  *
191  * While it guarantees that each task will complete before executing the next,
192  * there is no guarantee as to which thread from the \c pool individual tasks
193  * will execute. This normally only matters if your code relys on thread
194  * specific information, such as thread locals.
195  *
196  * Use ast_taskprocessor_unreference() to dispose of the returned \ref
197  * ast_taskprocessor.
198  *
199  * Only a single taskprocessor with a given name may exist. This function will fail
200  * if a taskprocessor with the given name already exists.
201  *
202  * \param name Name of the serializer. (must be unique)
203  * \param pool \ref ast_threadpool for execution.
204  * \return \ref ast_taskprocessor for enqueuing work.
205  * \return \c NULL on error.
206  */
207 struct ast_taskprocessor *ast_threadpool_serializer(const char *name, struct ast_threadpool *pool);
208
209 #endif /* ASTERISK_THREADPOOL_H */