3978e329907d89eabd93094e84f69ab53a1f7b88
[asterisk/asterisk.git] / include / asterisk / sched.h
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@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 /*! \file
20  * \brief Scheduler Routines (derived from cheops)
21  */
22
23 #ifndef _ASTERISK_SCHED_H
24 #define _ASTERISK_SCHED_H
25
26 #if defined(__cplusplus) || defined(c_plusplus)
27 extern "C" {
28 #endif
29
30 /*! \brief Max num of schedule structs
31  * \note The max number of schedule structs to keep around
32  * for use.  Undefine to disable schedule structure
33  * caching. (Only disable this on very low memory
34  * machines)
35  */
36 #define SCHED_MAX_CACHE 128
37
38 /*! \brief a loop construct to ensure that
39  * the scheduled task get deleted. The idea is that
40  * if we loop attempting to remove the scheduled task,
41  * then whatever callback had been running will complete
42  * and reinsert the task into the scheduler.
43  *
44  * Note that this is NOT always appropriate. This should 
45  * only be used for tasks whose callback may return non-zero 
46  * to indicate that the task needs to be rescheduled with the
47  * SAME id as previously.
48  *
49  * Some scheduler callbacks instead may reschedule the task themselves,
50  * thus removing the previous task id from the queue. If the task is rescheduled
51  * in this manner, then the id for the task will be different than before
52  * and so it makes no sense to use this macro. Note that if using the scheduler
53  * in this manner, it is perfectly acceptable for ast_sched_del to fail, and this
54  * macro should NOT be used.
55  */
56 #define AST_SCHED_DEL(sched, id) \
57         do { \
58                 int _count = 0; \
59                 while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \
60                         usleep(1); \
61                 } \
62                 if (_count == 10) \
63                         ast_debug(3, "Unable to cancel schedule ID %d.\n", id); \
64                 id = -1; \
65         } while (0);
66
67 #define AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, variable) \
68         do { \
69                 int _count = 0; \
70                 while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \
71                         usleep(1); \
72                 } \
73                 if (_count == 10) \
74                         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__); \
75                 id = ast_sched_add_variable(sched, when, callback, data, variable); \
76         } while (0);
77
78 #define AST_SCHED_REPLACE(id, sched, when, callback, data) \
79                 AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, 0)
80
81 struct sched_context;
82
83 /*! \brief New schedule context
84  * \note Create a scheduling context
85  * \return Returns a malloc'd sched_context structure, NULL on failure
86  */
87 struct sched_context *sched_context_create(void);
88
89 /*! \brief destroys a schedule context
90  * Destroys (free's) the given sched_context structure
91  * \param c Context to free
92  * \return Returns 0 on success, -1 on failure
93  */
94 void sched_context_destroy(struct sched_context *c);
95
96 /*! \brief callback for a cheops scheduler
97  * A cheops scheduler callback takes a pointer with callback data and
98  * \return returns a 0 if it should not be run again, or non-zero if it should be
99  * rescheduled to run again
100  */
101 typedef int (*ast_sched_cb)(const void *data);
102 #define AST_SCHED_CB(a) ((ast_sched_cb)(a))
103
104 /*! \brief Adds a scheduled event
105  * Schedule an event to take place at some point in the future.  callback
106  * will be called with data as the argument, when milliseconds into the
107  * future (approximately)
108  * If callback returns 0, no further events will be re-scheduled
109  * \param con Scheduler context to add
110  * \param when how many milliseconds to wait for event to occur
111  * \param callback function to call when the amount of time expires
112  * \param data data to pass to the callback
113  * \return Returns a schedule item ID on success, -1 on failure
114  */
115 int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data);
116
117 /*!
118  * \brief replace a scheduler entry
119  * \deprecated You should use the AST_SCHED_REPLACE() macro instead.
120  *
121  * This deletes the scheduler entry for old_id if it exists, and then
122  * calls ast_sched_add to create a new entry.  A negative old_id will
123  * be ignored.
124  *
125  * \retval -1 failure
126  * \retval otherwise, returns scheduled item ID
127  */
128 int ast_sched_replace(int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data);
129
130 /*!Adds a scheduled event with rescheduling support
131  * \param con Scheduler context to add
132  * \param when how many milliseconds to wait for event to occur
133  * \param callback function to call when the amount of time expires
134  * \param data data to pass to the callback
135  * \param variable If true, the result value of callback function will be
136  *       used for rescheduling
137  * Schedule an event to take place at some point in the future.  Callback
138  * will be called with data as the argument, when milliseconds into the
139  * future (approximately)
140  * If callback returns 0, no further events will be re-scheduled
141  * \return Returns a schedule item ID on success, -1 on failure
142  */
143 int ast_sched_add_variable(struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable);
144
145 /*!
146  * \brief replace a scheduler entry
147  * \deprecated You should use the AST_SCHED_REPLACE_VARIABLE() macro instead.
148  *
149  * This deletes the scheduler entry for old_id if it exists, and then
150  * calls ast_sched_add to create a new entry.  A negative old_id will
151  * be ignored.
152  *
153  * \retval -1 failure
154  * \retval otherwise, returns scheduled item ID
155  */
156 int ast_sched_replace_variable(int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable);
157
158 /*! \brief Deletes a scheduled event
159  * Remove this event from being run.  A procedure should not remove its own
160  * event, but return 0 instead.  In most cases, you should not call this
161  * routine directly, but use the AST_SCHED_DEL() macro instead (especially if
162  * you don't intend to do something different when it returns failure).
163  * \param con scheduling context to delete item from
164  * \param id ID of the scheduled item to delete
165  * \return Returns 0 on success, -1 on failure
166  */
167 int ast_sched_del(struct sched_context *con, int id);
168
169 /*! \brief Determines number of seconds until the next outstanding event to take place
170  * Determine the number of seconds until the next outstanding event
171  * should take place, and return the number of milliseconds until
172  * it needs to be run.  This value is perfect for passing to the poll
173  * call.
174  * \param con context to act upon
175  * \return Returns "-1" if there is nothing there are no scheduled events
176  * (and thus the poll should not timeout)
177  */
178 int ast_sched_wait(struct sched_context *con);
179
180 /*! \brief Runs the queue
181  * \param con Scheduling context to run
182  * Run the queue, executing all callbacks which need to be performed
183  * at this time.
184  * \param con context to act upon
185  * \return Returns the number of events processed.
186  */
187 int ast_sched_runq(struct sched_context *con);
188
189 /*! \brief Dumps the scheduler contents
190  * Debugging: Dump the contents of the scheduler to stderr
191  * \param con Context to dump
192  */
193 void ast_sched_dump(const struct sched_context *con);
194
195 /*! \brief Returns the number of seconds before an event takes place
196  * \param con Context to use
197  * \param id Id to dump
198  */
199 long ast_sched_when(struct sched_context *con,int id);
200
201 /*!
202  * \brief Convenience macro for objects and reference (add)
203  *
204  */
205 #define ast_sched_add_object(obj,con,when,callback) ast_sched_add((con),(when),(callback), ASTOBJ_REF((obj)))
206
207 /*!
208  * \brief Convenience macro for objects and reference (del)
209  *
210  */
211 #define ast_sched_del_object(obj,destructor,con,id) do { \
212         if ((id) > -1) { \
213                 ast_sched_del((con),(id)); \
214                 (id) = -1; \
215                 ASTOBJ_UNREF((obj),(destructor)); \
216         } \
217 } while(0)
218
219 #if defined(__cplusplus) || defined(c_plusplus)
220 }
221 #endif
222
223 #endif /* _ASTERISK_SCHED_H */