Wed Aug 18 22:33:56 2010

Asterisk developer's documentation


sched.h

Go to the documentation of this file.
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 
00031 /*! \brief Max num of schedule structs
00032  * \note The max number of schedule structs to keep around
00033  * for use.  Undefine to disable schedule structure
00034  * caching. (Only disable this on very low memory
00035  * machines)
00036  */
00037 #define SCHED_MAX_CACHE 128
00038 
00039 /*! \brief a loop construct to ensure that
00040  * the scheduled task get deleted. The idea is that
00041  * if we loop attempting to remove the scheduled task,
00042  * then whatever callback had been running will complete
00043  * and reinsert the task into the scheduler.
00044  *
00045  * Since macro expansion essentially works like pass-by-name
00046  * parameter passing, this macro will still work correctly even
00047  * if the id of the task to delete changes. This holds as long as 
00048  * the name of the id which could change is passed to the macro 
00049  * and not a copy of the value of the id.
00050  */
00051 #define AST_SCHED_DEL(sched, id) \
00052    do { \
00053       int _count = 0; \
00054       while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \
00055          usleep(1); \
00056       } \
00057       if (_count == 10) \
00058          ast_debug(3, "Unable to cancel schedule ID %d.\n", id); \
00059       id = -1; \
00060    } while (0);
00061 
00062 /*!
00063  * \brief schedule task to get deleted and call unref function
00064  * \sa AST_SCHED_DEL
00065  * \since 1.6.1
00066  */
00067 #define AST_SCHED_DEL_UNREF(sched, id, refcall)       \
00068    do { \
00069       int _count = 0; \
00070       while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \
00071          usleep(1); \
00072       } \
00073       if (_count == 10) \
00074          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__); \
00075       if (id > -1) \
00076          refcall; \
00077       id = -1; \
00078    } while (0);
00079 
00080 /*!
00081  * \brief schedule task to get deleted releasing the lock between attempts
00082  * \since 1.6.1
00083  */
00084 #define AST_SCHED_DEL_SPINLOCK(sched, id, lock) \
00085    ({ \
00086       int _count = 0; \
00087       int _sched_res = -1; \
00088       while (id > -1 && (_sched_res = ast_sched_del(sched, id)) && ++_count < 10) { \
00089          ast_mutex_unlock(lock); \
00090          usleep(1); \
00091          ast_mutex_lock(lock); \
00092       } \
00093       if (_count == 10 && option_debug > 2) { \
00094          ast_log(LOG_DEBUG, "Unable to cancel schedule ID %d.\n", id); \
00095       } \
00096       id = -1; \
00097       (_sched_res); \
00098    })
00099 
00100 #define AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, variable) \
00101    do { \
00102       int _count = 0; \
00103       while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \
00104          usleep(1); \
00105       } \
00106       if (_count == 10) \
00107          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__); \
00108       id = ast_sched_add_variable(sched, when, callback, data, variable); \
00109    } while (0);
00110 
00111 #define AST_SCHED_REPLACE(id, sched, when, callback, data) \
00112       AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, 0)
00113 
00114 /*!
00115  * \note Not currently used in the source?
00116  * \since 1.6.1
00117  */
00118 #define AST_SCHED_REPLACE_VARIABLE_UNREF(id, sched, when, callback, data, variable, unrefcall, addfailcall, refcall) \
00119    do { \
00120       int _count = 0, _res=1;                                \
00121       void *_data = (void *)ast_sched_find_data(sched, id);       \
00122       while (id > -1 && (_res = ast_sched_del(sched, id) && _count++ < 10)) { \
00123          usleep(1); \
00124       } \
00125       if (!_res && _data)                    \
00126          unrefcall;  /* should ref _data! */    \
00127       if (_count == 10) \
00128          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__); \
00129       refcall; \
00130       id = ast_sched_add_variable(sched, when, callback, data, variable); \
00131       if (id == -1)  \
00132          addfailcall;   \
00133    } while (0);
00134 
00135 #define AST_SCHED_REPLACE_UNREF(id, sched, when, callback, data, unrefcall, addfailcall, refcall) \
00136    AST_SCHED_REPLACE_VARIABLE_UNREF(id, sched, when, callback, data, 0, unrefcall, addfailcall, refcall)
00137 
00138 struct sched_context;
00139 
00140 /*! \brief New schedule context
00141  * \note Create a scheduling context
00142  * \return Returns a malloc'd sched_context structure, NULL on failure
00143  */
00144 struct sched_context *sched_context_create(void);
00145 
00146 /*! \brief destroys a schedule context
00147  * Destroys (free's) the given sched_context structure
00148  * \param c Context to free
00149  * \return Returns 0 on success, -1 on failure
00150  */
00151 void sched_context_destroy(struct sched_context *c);
00152 
00153 /*! \brief callback for a cheops scheduler
00154  * A cheops scheduler callback takes a pointer with callback data and
00155  * \return returns a 0 if it should not be run again, or non-zero if it should be
00156  * rescheduled to run again
00157  */
00158 typedef int (*ast_sched_cb)(const void *data);
00159 #define AST_SCHED_CB(a) ((ast_sched_cb)(a))
00160 
00161 struct ast_cb_names {
00162    int numassocs;
00163    char *list[10];
00164    ast_sched_cb cblist[10];
00165 };
00166 
00167 /*!
00168  * \brief Show statics on what it is in the schedule queue
00169  * \param con Schedule context to check
00170  * \param buf dynamic string to store report
00171  * \param cbnames to check against
00172  * \since 1.6.1
00173  */
00174 void ast_sched_report(struct sched_context *con, struct ast_str **buf, struct ast_cb_names *cbnames);
00175       
00176 /*! \brief Adds a scheduled event
00177  * Schedule an event to take place at some point in the future.  callback
00178  * will be called with data as the argument, when milliseconds into the
00179  * future (approximately)
00180  * If callback returns 0, no further events will be re-scheduled
00181  * \param con Scheduler context to add
00182  * \param when how many milliseconds to wait for event to occur
00183  * \param callback function to call when the amount of time expires
00184  * \param data data to pass to the callback
00185  * \return Returns a schedule item ID on success, -1 on failure
00186  */
00187 int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result;
00188 
00189 /*!
00190  * \brief replace a scheduler entry
00191  * \deprecated You should use the AST_SCHED_REPLACE() macro instead.
00192  *
00193  * This deletes the scheduler entry for old_id if it exists, and then
00194  * calls ast_sched_add to create a new entry.  A negative old_id will
00195  * be ignored.
00196  *
00197  * \retval -1 failure
00198  * \retval otherwise, returns scheduled item ID
00199  */
00200 int ast_sched_replace(int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result;
00201 
00202 /*!Adds a scheduled event with rescheduling support
00203  * \param con Scheduler context to add
00204  * \param when how many milliseconds to wait for event to occur
00205  * \param callback function to call when the amount of time expires
00206  * \param data data to pass to the callback
00207  * \param variable If true, the result value of callback function will be
00208  *       used for rescheduling
00209  * Schedule an event to take place at some point in the future.  Callback
00210  * will be called with data as the argument, when milliseconds into the
00211  * future (approximately)
00212  * If callback returns 0, no further events will be re-scheduled
00213  * \return Returns a schedule item ID on success, -1 on failure
00214  */
00215 int ast_sched_add_variable(struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result;
00216 
00217 /*!
00218  * \brief replace a scheduler entry
00219  * \deprecated You should use the AST_SCHED_REPLACE_VARIABLE() macro instead.
00220  *
00221  * This deletes the scheduler entry for old_id if it exists, and then
00222  * calls ast_sched_add to create a new entry.  A negative old_id will
00223  * be ignored.
00224  *
00225  * \retval -1 failure
00226  * \retval otherwise, returns scheduled item ID
00227  */
00228 int ast_sched_replace_variable(int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result;
00229 
00230    
00231 /*! 
00232  * \brief Find a sched structure and return the data field associated with it. 
00233  * \param con scheduling context in which to search fro the matching id
00234  * \param id ID of the scheduled item to find
00235  * \return the data field from the matching sched struct if found; else return NULL if not found.
00236  * \since 1.6.1
00237  */
00238 
00239 const void *ast_sched_find_data(struct sched_context *con, int id);
00240    
00241 /*! \brief Deletes a scheduled event
00242  * Remove this event from being run.  A procedure should not remove its own
00243  * event, but return 0 instead.  In most cases, you should not call this
00244  * routine directly, but use the AST_SCHED_DEL() macro instead (especially if
00245  * you don't intend to do something different when it returns failure).
00246  * \param con scheduling context to delete item from
00247  * \param id ID of the scheduled item to delete
00248  * \return Returns 0 on success, -1 on failure
00249  */
00250 #ifndef AST_DEVMODE
00251 int ast_sched_del(struct sched_context *con, int id) attribute_warn_unused_result;
00252 #else
00253 int _ast_sched_del(struct sched_context *con, int id, const char *file, int line, const char *function) attribute_warn_unused_result;
00254 #define  ast_sched_del(a, b)  _ast_sched_del(a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00255 #endif
00256 
00257 /*! \brief Determines number of seconds until the next outstanding event to take place
00258  * Determine the number of seconds until the next outstanding event
00259  * should take place, and return the number of milliseconds until
00260  * it needs to be run.  This value is perfect for passing to the poll
00261  * call.
00262  * \param con context to act upon
00263  * \return Returns "-1" if there is nothing there are no scheduled events
00264  * (and thus the poll should not timeout)
00265  */
00266 int ast_sched_wait(struct sched_context *con) attribute_warn_unused_result;
00267 
00268 /*! \brief Runs the queue
00269  * \param con Scheduling context to run
00270  * Run the queue, executing all callbacks which need to be performed
00271  * at this time.
00272  * \param con context to act upon
00273  * \return Returns the number of events processed.
00274  */
00275 int ast_sched_runq(struct sched_context *con);
00276 
00277 /*! \brief Dumps the scheduler contents
00278  * Debugging: Dump the contents of the scheduler to stderr
00279  * \param con Context to dump
00280  */
00281 void ast_sched_dump(struct sched_context *con);
00282 
00283 /*! \brief Returns the number of seconds before an event takes place
00284  * \param con Context to use
00285  * \param id Id to dump
00286  */
00287 long ast_sched_when(struct sched_context *con,int id);
00288 
00289 /*!
00290  * \brief Convenience macro for objects and reference (add)
00291  *
00292  */
00293 #define ast_sched_add_object(obj,con,when,callback) ast_sched_add((con),(when),(callback), ASTOBJ_REF((obj)))
00294 
00295 /*!
00296  * \brief Convenience macro for objects and reference (del)
00297  *
00298  */
00299 #define ast_sched_del_object(obj,destructor,con,id) do { \
00300    if ((id) > -1) { \
00301       ast_sched_del((con),(id)); \
00302       (id) = -1; \
00303       ASTOBJ_UNREF((obj),(destructor)); \
00304    } \
00305 } while(0)
00306 
00307 #if defined(__cplusplus) || defined(c_plusplus)
00308 }
00309 #endif
00310 
00311 #endif /* _ASTERISK_SCHED_H */

Generated on Wed Aug 18 22:33:56 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7