00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 1999 - 2005, Digium, Inc. 00005 * 00006 * Mark Spencer <markster@digium.com> 00007 * 00008 * See http://www.asterisk.org for more information about 00009 * the Asterisk project. Please do not directly contact 00010 * any of the maintainers of this project for assistance; 00011 * the project provides a web site, mailing lists and IRC 00012 * channels for your use. 00013 * 00014 * This program is free software, distributed under the terms of 00015 * the GNU General Public License Version 2. See the LICENSE file 00016 * at the top of the source tree. 00017 */ 00018 00019 /*! \file 00020 * \brief Scheduler Routines (derived from cheops) 00021 */ 00022 00023 #ifndef _ASTERISK_SCHED_H 00024 #define _ASTERISK_SCHED_H 00025 00026 #if defined(__cplusplus) || defined(c_plusplus) 00027 extern "C" { 00028 #endif 00029 00030 /*! \brief Max num of schedule structs 00031 * \note The max number of schedule structs to keep around 00032 * for use. Undefine to disable schedule structure 00033 * caching. (Only disable this on very low memory 00034 * machines) 00035 */ 00036 #define SCHED_MAX_CACHE 128 00037 00038 /*! \brief a loop construct to ensure that 00039 * the scheduled task get deleted. The idea is that 00040 * if we loop attempting to remove the scheduled task, 00041 * then whatever callback had been running will complete 00042 * and reinsert the task into the scheduler. 00043 * 00044 * Since macro expansion essentially works like pass-by-name 00045 * parameter passing, this macro will still work correctly even 00046 * if the id of the task to delete changes. This holds as long as 00047 * the name of the id which could change is passed to the macro 00048 * and not a copy of the value of the id. 00049 */ 00050 #define AST_SCHED_DEL(sched, id) \ 00051 do { \ 00052 int _count = 0; \ 00053 while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \ 00054 usleep(1); \ 00055 } \ 00056 if (_count == 10) \ 00057 ast_debug(3, "Unable to cancel schedule ID %d.\n", id); \ 00058 id = -1; \ 00059 } while (0); 00060 00061 #define AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, variable) \ 00062 do { \ 00063 int _count = 0; \ 00064 while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \ 00065 usleep(1); \ 00066 } \ 00067 if (_count == 10) \ 00068 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__); \ 00069 id = ast_sched_add_variable(sched, when, callback, data, variable); \ 00070 } while (0); 00071 00072 #define AST_SCHED_REPLACE(id, sched, when, callback, data) \ 00073 AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, 0) 00074 00075 struct sched_context; 00076 00077 /*! \brief New schedule context 00078 * \note Create a scheduling context 00079 * \return Returns a malloc'd sched_context structure, NULL on failure 00080 */ 00081 struct sched_context *sched_context_create(void); 00082 00083 /*! \brief destroys a schedule context 00084 * Destroys (free's) the given sched_context structure 00085 * \param c Context to free 00086 * \return Returns 0 on success, -1 on failure 00087 */ 00088 void sched_context_destroy(struct sched_context *c); 00089 00090 /*! \brief callback for a cheops scheduler 00091 * A cheops scheduler callback takes a pointer with callback data and 00092 * \return returns a 0 if it should not be run again, or non-zero if it should be 00093 * rescheduled to run again 00094 */ 00095 typedef int (*ast_sched_cb)(const void *data); 00096 #define AST_SCHED_CB(a) ((ast_sched_cb)(a)) 00097 00098 /*! \brief Adds a scheduled event 00099 * Schedule an event to take place at some point in the future. callback 00100 * will be called with data as the argument, when milliseconds into the 00101 * future (approximately) 00102 * If callback returns 0, no further events will be re-scheduled 00103 * \param con Scheduler context to add 00104 * \param when how many milliseconds to wait for event to occur 00105 * \param callback function to call when the amount of time expires 00106 * \param data data to pass to the callback 00107 * \return Returns a schedule item ID on success, -1 on failure 00108 */ 00109 int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data); 00110 00111 /*! 00112 * \brief replace a scheduler entry 00113 * \deprecated You should use the AST_SCHED_REPLACE() macro instead. 00114 * 00115 * This deletes the scheduler entry for old_id if it exists, and then 00116 * calls ast_sched_add to create a new entry. A negative old_id will 00117 * be ignored. 00118 * 00119 * \retval -1 failure 00120 * \retval otherwise, returns scheduled item ID 00121 */ 00122 int ast_sched_replace(int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data); 00123 00124 /*!Adds a scheduled event with rescheduling support 00125 * \param con Scheduler context to add 00126 * \param when how many milliseconds to wait for event to occur 00127 * \param callback function to call when the amount of time expires 00128 * \param data data to pass to the callback 00129 * \param variable If true, the result value of callback function will be 00130 * used for rescheduling 00131 * Schedule an event to take place at some point in the future. Callback 00132 * will be called with data as the argument, when milliseconds into the 00133 * future (approximately) 00134 * If callback returns 0, no further events will be re-scheduled 00135 * \return Returns a schedule item ID on success, -1 on failure 00136 */ 00137 int ast_sched_add_variable(struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable); 00138 00139 /*! 00140 * \brief replace a scheduler entry 00141 * \deprecated You should use the AST_SCHED_REPLACE_VARIABLE() macro instead. 00142 * 00143 * This deletes the scheduler entry for old_id if it exists, and then 00144 * calls ast_sched_add to create a new entry. A negative old_id will 00145 * be ignored. 00146 * 00147 * \retval -1 failure 00148 * \retval otherwise, returns scheduled item ID 00149 */ 00150 int ast_sched_replace_variable(int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable); 00151 00152 /*! \brief Deletes a scheduled event 00153 * Remove this event from being run. A procedure should not remove its own 00154 * event, but return 0 instead. In most cases, you should not call this 00155 * routine directly, but use the AST_SCHED_DEL() macro instead (especially if 00156 * you don't intend to do something different when it returns failure). 00157 * \param con scheduling context to delete item from 00158 * \param id ID of the scheduled item to delete 00159 * \return Returns 0 on success, -1 on failure 00160 */ 00161 #ifndef AST_DEVMODE 00162 int ast_sched_del(struct sched_context *con, int id); 00163 #else 00164 int _ast_sched_del(struct sched_context *con, int id, const char *file, int line, const char *function); 00165 #define ast_sched_del(a, b) _ast_sched_del(a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__) 00166 #endif 00167 00168 /*! \brief Determines number of seconds until the next outstanding event to take place 00169 * Determine the number of seconds until the next outstanding event 00170 * should take place, and return the number of milliseconds until 00171 * it needs to be run. This value is perfect for passing to the poll 00172 * call. 00173 * \param con context to act upon 00174 * \return Returns "-1" if there is nothing there are no scheduled events 00175 * (and thus the poll should not timeout) 00176 */ 00177 int ast_sched_wait(struct sched_context *con); 00178 00179 /*! \brief Runs the queue 00180 * \param con Scheduling context to run 00181 * Run the queue, executing all callbacks which need to be performed 00182 * at this time. 00183 * \param con context to act upon 00184 * \return Returns the number of events processed. 00185 */ 00186 int ast_sched_runq(struct sched_context *con); 00187 00188 /*! \brief Dumps the scheduler contents 00189 * Debugging: Dump the contents of the scheduler to stderr 00190 * \param con Context to dump 00191 */ 00192 void ast_sched_dump(const struct sched_context *con); 00193 00194 /*! \brief Returns the number of seconds before an event takes place 00195 * \param con Context to use 00196 * \param id Id to dump 00197 */ 00198 long ast_sched_when(struct sched_context *con,int id); 00199 00200 /*! 00201 * \brief Convenience macro for objects and reference (add) 00202 * 00203 */ 00204 #define ast_sched_add_object(obj,con,when,callback) ast_sched_add((con),(when),(callback), ASTOBJ_REF((obj))) 00205 00206 /*! 00207 * \brief Convenience macro for objects and reference (del) 00208 * 00209 */ 00210 #define ast_sched_del_object(obj,destructor,con,id) do { \ 00211 if ((id) > -1) { \ 00212 ast_sched_del((con),(id)); \ 00213 (id) = -1; \ 00214 ASTOBJ_UNREF((obj),(destructor)); \ 00215 } \ 00216 } while(0) 00217 00218 #if defined(__cplusplus) || defined(c_plusplus) 00219 } 00220 #endif 00221 00222 #endif /* _ASTERISK_SCHED_H */