Asterisk - The Open Source Telephony Project  GIT-master-a24979a
sched.h
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2010, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  * Russell Bryant <russell@digium.com>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19 
20 /*! \file
21  * \brief Scheduler Routines (derived from cheops)
22  */
23 
24 #ifndef _ASTERISK_SCHED_H
25 #define _ASTERISK_SCHED_H
26 
27 #if defined(__cplusplus) || defined(c_plusplus)
28 extern "C" {
29 #endif
30 
31 /*!
32  * \brief Remove a scheduler entry
33  *
34  * This is a loop construct to ensure that
35  * the scheduled task get deleted. The idea is that
36  * if we loop attempting to remove the scheduled task,
37  * then whatever callback had been running will complete
38  * and reinsert the task into the scheduler.
39  *
40  * Since macro expansion essentially works like pass-by-name
41  * parameter passing, this macro will still work correctly even
42  * if the id of the task to delete changes. This holds as long as
43  * the name of the id which could change is passed to the macro
44  * and not a copy of the value of the id.
45  */
46 #define AST_SCHED_DEL(sched, id) \
47  ({ \
48  int _count = 0; \
49  int _sched_res = -1; \
50  while (id > -1 && (_sched_res = ast_sched_del(sched, id)) && ++_count < 10) \
51  usleep(1); \
52  if (_count == 10) { \
53  ast_debug(3, "Unable to cancel schedule ID %d.\n", id); \
54  } \
55  id = -1; \
56  (_sched_res); \
57  })
58 
59 #define AST_SCHED_DEL_ACCESSOR(sched, obj, getter, setter) \
60  ({ \
61  int _count = 0; \
62  int _sched_res = -1; \
63  while (getter(obj) > -1 && (_sched_res = ast_sched_del(sched, getter(obj))) && ++_count < 10) \
64  usleep(1); \
65  if (_count == 10) { \
66  ast_debug(3, "Unable to cancel schedule ID %d.\n", getter(obj)); \
67  } \
68  setter(obj, -1); \
69  (_sched_res); \
70  })
71 
72 /*!
73  * \brief schedule task to get deleted and call unref function
74  *
75  * Only calls the unref function if the task is actually deleted by
76  * ast_sched_del_nonrunning. If a failure occurs or the task is
77  * currently running and not rescheduled then refcall is not invoked.
78  *
79  * \sa AST_SCHED_DEL
80  * \since 1.6.1
81  */
82 #define AST_SCHED_DEL_UNREF(sched, id, refcall) \
83  do { \
84  int _count = 0, _id, _ret = 0; \
85  while ((_id = id) > -1 && (( _ret = ast_sched_del_nonrunning(sched, _id)) == -1) && ++_count < 10) { \
86  usleep(1); \
87  } \
88  if (_count == 10) { \
89  ast_log(LOG_WARNING, "Unable to cancel schedule ID %d. This is probably a bug (%s: %s, line %d).\n", _id, __FILE__, __PRETTY_FUNCTION__, __LINE__); \
90  } else if (_id > -1 && _ret >-2) { \
91  refcall; \
92  id = -1; \
93  } \
94  } while (0);
95 
96 /*!
97  * \brief schedule task to get deleted releasing the lock between attempts
98  * \since 1.6.1
99  */
100 #define AST_SCHED_DEL_SPINLOCK(sched, id, lock) \
101  ({ \
102  int _count = 0; \
103  int _sched_res = -1; \
104  while (id > -1 && (_sched_res = ast_sched_del(sched, id)) && ++_count < 10) { \
105  ast_mutex_unlock(lock); \
106  usleep(1); \
107  ast_mutex_lock(lock); \
108  } \
109  if (_count == 10) { \
110  ast_debug(3, "Unable to cancel schedule ID %d.\n", id); \
111  } \
112  id = -1; \
113  (_sched_res); \
114  })
115 
116 #define AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, variable) \
117  do { \
118  int _count = 0; \
119  while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \
120  usleep(1); \
121  } \
122  if (_count == 10) \
123  ast_log(LOG_WARNING, "Unable to cancel schedule ID %d. This is probably a bug (%s: %s, line %d).\n", id, __FILE__, __PRETTY_FUNCTION__, __LINE__); \
124  id = ast_sched_add_variable(sched, when, callback, data, variable); \
125  } while (0);
126 
127 #define AST_SCHED_REPLACE(id, sched, when, callback, data) \
128  AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, 0)
129 
130 /*!
131  * \note Not currently used in the source?
132  * \since 1.6.1
133  */
134 #define AST_SCHED_REPLACE_VARIABLE_UNREF(id, sched, when, callback, data, variable, unrefcall, addfailcall, refcall) \
135  do { \
136  int _count = 0, _res=1; \
137  void *_data = (void *)ast_sched_find_data(sched, id); \
138  while (id > -1 && (_res = ast_sched_del(sched, id) && _count++ < 10)) { \
139  usleep(1); \
140  } \
141  if (!_res && _data && _data != data) \
142  unrefcall; /* should ref _data! */ \
143  if (_count == 10) \
144  ast_log(LOG_WARNING, "Unable to cancel schedule ID %d. This is probably a bug (%s: %s, line %d).\n", id, __FILE__, __PRETTY_FUNCTION__, __LINE__); \
145  if (_data != data) \
146  refcall; \
147  id = ast_sched_add_variable(sched, when, callback, data, variable); \
148  if (id == -1) \
149  addfailcall; \
150  } while (0);
151 
152 #define AST_SCHED_REPLACE_UNREF(id, sched, when, callback, data, unrefcall, addfailcall, refcall) \
153  AST_SCHED_REPLACE_VARIABLE_UNREF(id, sched, when, callback, data, 0, unrefcall, addfailcall, refcall)
154 
155 /*!
156  * \brief Create a scheduler context
157  *
158  * \retval NULL on failure
159  * \return a malloc'd sched_context structure
160  */
162 
163 /*!
164  * \brief destroys a schedule context
165  *
166  * \param c Context to free
167  */
169 
170 /*!
171  * \brief scheduler callback
172  *
173  * A scheduler callback takes a pointer with callback data and
174  *
175  * \retval 0 if the callback should not be rescheduled
176  * \retval non-zero if the callback should be scheduled again
177  */
178 typedef int (*ast_sched_cb)(const void *data);
179 #define AST_SCHED_CB(a) ((ast_sched_cb)(a))
180 
181 /*!
182  * \brief Clean all scheduled events with matching callback.
183  *
184  * \param con Scheduler Context
185  * \param match Callback to match
186  * \param cleanup_cb Callback to run
187  *
188  * \note The return of cleanup_cb is ignored. No events are rescheduled.
189  */
191 
192 struct ast_cb_names {
194  char *list[10];
196 };
197 
198 /*!
199  * \brief Show statics on what it is in the schedule queue
200  * \param con Schedule context to check
201  * \param buf dynamic string to store report
202  * \param cbnames to check against
203  * \since 1.6.1
204  */
205 void ast_sched_report(struct ast_sched_context *con, struct ast_str **buf, struct ast_cb_names *cbnames);
206 
207 /*!
208  * \brief Adds a scheduled event
209  *
210  * Schedule an event to take place at some point in the future. callback
211  * will be called with data as the argument, when milliseconds into the
212  * future (approximately)
213  *
214  * If callback returns 0, no further events will be re-scheduled
215  *
216  * \param con Scheduler context to add
217  * \param when how many milliseconds to wait for event to occur
218  * \param callback function to call when the amount of time expires
219  * \param data data to pass to the callback
220  *
221  * \retval -1 on failure
222  * \return schedule item ID
223  */
224 int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result;
225 
226 /*!
227  * \brief replace a scheduler entry
228  * \deprecated You should use the AST_SCHED_REPLACE() macro instead.
229  *
230  * This deletes the scheduler entry for old_id if it exists, and then
231  * calls ast_sched_add to create a new entry. A negative old_id will
232  * be ignored.
233  *
234  * \retval -1 on failure
235  * \return scheduled item ID
236  */
237 int ast_sched_replace(int old_id, struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result;
238 
239 /*!
240  * \brief Adds a scheduled event with rescheduling support
241  *
242  * \param con Scheduler context to add
243  * \param when how many milliseconds to wait for event to occur
244  * \param callback function to call when the amount of time expires
245  * \param data data to pass to the callback
246  * \param variable If true, the result value of callback function will be
247  * used for rescheduling
248  *
249  * Schedule an event to take place at some point in the future. Callback
250  * will be called with data as the argument, when milliseconds into the
251  * future (approximately)
252  *
253  * If callback returns 0, no further events will be re-scheduled
254  *
255  * \retval -1 on failure
256  * \return scheduled item ID
257  */
258 int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result;
259 
260 /*!
261  * \brief replace a scheduler entry
262  * \deprecated You should use the AST_SCHED_REPLACE_VARIABLE() macro instead.
263  *
264  * This deletes the scheduler entry for old_id if it exists, and then
265  * calls ast_sched_add to create a new entry. A negative old_id will
266  * be ignored.
267  *
268  * \retval -1 on failure
269  * \return scheduled item ID
270  */
271 int ast_sched_replace_variable(int old_id, struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result;
272 
273 /*!
274  * \brief Find a sched structure and return the data field associated with it.
275  *
276  * \param con scheduling context in which to search fro the matching id
277  * \param id ID of the scheduled item to find
278  *
279  * \retval NULL if not found
280  * \return the data field from the matching sched struct if found.
281  *
282  * \since 1.6.1
283  */
284 const void *ast_sched_find_data(struct ast_sched_context *con, int id);
285 
286 /*!
287  * \brief Deletes a scheduled event
288  *
289  * Remove this event from being run. A procedure should not remove its own
290  * event, but return 0 instead. In most cases, you should not call this
291  * routine directly, but use the AST_SCHED_DEL() macro instead (especially if
292  * you don't intend to do something different when it returns failure).
293  *
294  * \param con scheduling context to delete item from
295  * \param id ID of the scheduled item to delete
296  *
297  * \retval -1 on failure
298  * \retval 0 on success
299  *
300  * \deprecated in favor of ast_sched_del_nonrunning which checks if the event is running and rescheduled
301  *
302  */
304 
305 /*!
306  * \brief Deletes a scheduled event with care against the event running
307  *
308  * Remove this event from being run. A procedure should not remove its own
309  * event, but return 0 instead. In most cases, you should not call this
310  * routine directly, but use the AST_SCHED_DEL() macro instead (especially if
311  * you don't intend to do something different when it returns failure).
312  *
313  * \param con scheduling context to delete item from
314  * \param id ID of the scheduled item to delete
315  *
316  * \retval -1 on failure
317  * \retval -2 event was running but was deleted because it was not rescheduled
318  * \retval 0 on success
319  */
321 
322 /*!
323  * \brief Determines number of seconds until the next outstanding event to take place
324  *
325  * Determine the number of seconds until the next outstanding event
326  * should take place, and return the number of milliseconds until
327  * it needs to be run. This value is perfect for passing to the poll
328  * call.
329  *
330  * \param con context to act upon
331  *
332  * \retval -1 if there is nothing there are no scheduled events
333  * (and thus the poll should not timeout)
334  */
336 
337 /*!
338  * \brief Runs the queue
339  *
340  * Run the queue, executing all callbacks which need to be performed
341  * at this time.
342  *
343  * \param con Scheduling context to run
344  *
345  * \return the number of events processed.
346  */
347 int ast_sched_runq(struct ast_sched_context *con);
348 
349 /*!
350  * \brief Dumps the scheduler contents
351  *
352  * Debugging: Dump the contents of the scheduler to stderr
353  *
354  * \param con Context to dump
355  */
356 void ast_sched_dump(struct ast_sched_context *con);
357 
358 /*!
359  * \brief Returns the number of seconds before an event takes place
360  *
361  * \param con Context to use
362  * \param id Id to dump
363  */
364 long ast_sched_when(struct ast_sched_context *con,int id);
365 
366 /*!
367  * \brief Convenience macro for objects and reference (add)
368  *
369  */
370 #define ast_sched_add_object(obj,con,when,callback) ast_sched_add((con),(when),(callback), ASTOBJ_REF((obj)))
371 
372 /*!
373  * \brief Convenience macro for objects and reference (del)
374  *
375  */
376 #define ast_sched_del_object(obj,destructor,con,id) do { \
377  if ((id) > -1) { \
378  ast_sched_del((con),(id)); \
379  (id) = -1; \
380  ASTOBJ_UNREF((obj),(destructor)); \
381  } \
382 } while(0)
383 
384 /*!
385  * \brief Start a thread for processing scheduler entries
386  *
387  * \param con the scheduler context this thread will manage
388  *
389  * \retval 0 success
390  * \retval non-zero failure
391  */
393 
394 #if defined(__cplusplus) || defined(c_plusplus)
395 }
396 #endif
397 
398 #endif /* _ASTERISK_SCHED_H */
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2312
#define attribute_warn_unused_result
Definition: compiler.h:71
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int cleanup_cb(void *obj, void *arg, int flags)
Definition: res_stasis.c:309
const void * ast_sched_find_data(struct ast_sched_context *con, int id)
Find a sched structure and return the data field associated with it.
Definition: sched.c:589
int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event.
Definition: sched.c:614
void ast_sched_report(struct ast_sched_context *con, struct ast_str **buf, struct ast_cb_names *cbnames)
Show statics on what it is in the schedule queue.
Definition: sched.c:705
void ast_sched_clean_by_callback(struct ast_sched_context *con, ast_sched_cb match, ast_sched_cb cleanup_cb)
Clean all scheduled events with matching callback.
Definition: sched.c:409
long ast_sched_when(struct ast_sched_context *con, int id)
Returns the number of seconds before an event takes place.
Definition: sched.c:851
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:238
int ast_sched_replace(int old_id, struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
replace a scheduler entry
Definition: sched.c:559
void ast_sched_dump(struct ast_sched_context *con)
Dumps the scheduler contents.
Definition: sched.c:743
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
Definition: sched.c:567
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:271
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
Definition: sched.c:197
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:786
int ast_sched_del_nonrunning(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event with care against the event running.
Definition: sched.c:627
int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result
Adds a scheduled event with rescheduling support.
Definition: sched.c:526
int(* ast_sched_cb)(const void *data)
scheduler callback
Definition: sched.h:178
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
Definition: sched.c:433
int ast_sched_replace_variable(int old_id, struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result
replace a scheduler entry
Definition: sched.c:514
char * list[10]
Definition: sched.h:194
int numassocs
Definition: sched.h:193
ast_sched_cb cblist[10]
Definition: sched.h:195
Support for dynamic strings.
Definition: strings.h:604
static struct test_val c