Sat Mar 10 01:54:26 2012

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    ({ \
00053       int _count = 0; \
00054       int _sched_res = -1; \
00055       while (id > -1 && (_sched_res = ast_sched_del(sched, id)) && ++_count < 10) \
00056          usleep(1); \
00057       if (_count == 10 && option_debug > 2) { \
00058          ast_log(LOG_DEBUG, "Unable to cancel schedule ID %d.\n", id); \
00059       } \
00060       id = -1; \
00061       (_sched_res); \
00062    })
00063 
00064 /*!
00065  * \brief schedule task to get deleted and call unref function
00066  * \sa AST_SCHED_DEL
00067  * \since 1.6.1
00068  */
00069 #define AST_SCHED_DEL_UNREF(sched, id, refcall)       \
00070    do { \
00071       int _count = 0; \
00072       while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \
00073          usleep(1); \
00074       } \
00075       if (_count == 10) \
00076          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__); \
00077       if (id > -1) \
00078          refcall; \
00079       id = -1; \
00080    } while (0);
00081 
00082 /*!
00083  * \brief schedule task to get deleted releasing the lock between attempts
00084  * \since 1.6.1
00085  */
00086 #define AST_SCHED_DEL_SPINLOCK(sched, id, lock) \
00087    ({ \
00088       int _count = 0; \
00089       int _sched_res = -1; \
00090       while (id > -1 && (_sched_res = ast_sched_del(sched, id)) && ++_count < 10) { \
00091          ast_mutex_unlock(lock); \
00092          usleep(1); \
00093          ast_mutex_lock(lock); \
00094       } \
00095       if (_count == 10 && option_debug > 2) { \
00096          ast_log(LOG_DEBUG, "Unable to cancel schedule ID %d.\n", id); \
00097       } \
00098       id = -1; \
00099       (_sched_res); \
00100    })
00101 
00102 #define AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, variable) \
00103    do { \
00104       int _count = 0; \
00105       while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \
00106          usleep(1); \
00107       } \
00108       if (_count == 10) \
00109          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__); \
00110       id = ast_sched_add_variable(sched, when, callback, data, variable); \
00111    } while (0);
00112 
00113 #define AST_SCHED_REPLACE(id, sched, when, callback, data) \
00114       AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, 0)
00115 
00116 /*!
00117  * \note Not currently used in the source?
00118  * \since 1.6.1
00119  */
00120 #define AST_SCHED_REPLACE_VARIABLE_UNREF(id, sched, when, callback, data, variable, unrefcall, addfailcall, refcall) \
00121    do { \
00122       int _count = 0, _res=1;                                \
00123       void *_data = (void *)ast_sched_find_data(sched, id);       \
00124       while (id > -1 && (_res = ast_sched_del(sched, id) && _count++ < 10)) { \
00125          usleep(1); \
00126       } \
00127       if (!_res && _data)                    \
00128          unrefcall;  /* should ref _data! */    \
00129       if (_count == 10) \
00130          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__); \
00131       refcall; \
00132       id = ast_sched_add_variable(sched, when, callback, data, variable); \
00133       if (id == -1)  \
00134          addfailcall;   \
00135    } while (0);
00136 
00137 #define AST_SCHED_REPLACE_UNREF(id, sched, when, callback, data, unrefcall, addfailcall, refcall) \
00138    AST_SCHED_REPLACE_VARIABLE_UNREF(id, sched, when, callback, data, 0, unrefcall, addfailcall, refcall)
00139 
00140 struct sched_context;
00141 
00142 /*! \brief New schedule context
00143  * \note Create a scheduling context
00144  * \return Returns a malloc'd sched_context structure, NULL on failure
00145  */
00146 struct sched_context *sched_context_create(void);
00147 
00148 /*! \brief destroys a schedule context
00149  * Destroys (free's) the given sched_context structure
00150  * \param c Context to free
00151  * \return Returns 0 on success, -1 on failure
00152  */
00153 void sched_context_destroy(struct sched_context *c);
00154 
00155 /*! \brief callback for a cheops scheduler
00156  * A cheops scheduler callback takes a pointer with callback data and
00157  * \return returns a 0 if it should not be run again, or non-zero if it should be
00158  * rescheduled to run again
00159  */
00160 typedef int (*ast_sched_cb)(const void *data);
00161 #define AST_SCHED_CB(a) ((ast_sched_cb)(a))
00162 
00163 struct ast_cb_names {
00164    int numassocs;
00165    char *list[10];
00166    ast_sched_cb cblist[10];
00167 };
00168 
00169 /*!
00170  * \brief Show statics on what it is in the schedule queue
00171  * \param con Schedule context to check
00172  * \param buf dynamic string to store report
00173  * \param cbnames to check against
00174  * \since 1.6.1
00175  */
00176 void ast_sched_report(struct sched_context *con, struct ast_str **buf, struct ast_cb_names *cbnames);
00177       
00178 /*! \brief Adds a scheduled event
00179  * Schedule an event to take place at some point in the future.  callback
00180  * will be called with data as the argument, when milliseconds into the
00181  * future (approximately)
00182  * If callback returns 0, no further events will be re-scheduled
00183  * \param con Scheduler context to add
00184  * \param when how many milliseconds to wait for event to occur
00185  * \param callback function to call when the amount of time expires
00186  * \param data data to pass to the callback
00187  * \return Returns a schedule item ID on success, -1 on failure
00188  */
00189 int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result;
00190 
00191 /*!
00192  * \brief replace a scheduler entry
00193  * \deprecated You should use the AST_SCHED_REPLACE() macro instead.
00194  *
00195  * This deletes the scheduler entry for old_id if it exists, and then
00196  * calls ast_sched_add to create a new entry.  A negative old_id will
00197  * be ignored.
00198  *
00199  * \retval -1 failure
00200  * \retval otherwise, returns scheduled item ID
00201  */
00202 int ast_sched_replace(int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result;
00203 
00204 /*!Adds a scheduled event with rescheduling support
00205  * \param con Scheduler context to add
00206  * \param when how many milliseconds to wait for event to occur
00207  * \param callback function to call when the amount of time expires
00208  * \param data data to pass to the callback
00209  * \param variable If true, the result value of callback function will be
00210  *       used for rescheduling
00211  * Schedule an event to take place at some point in the future.  Callback
00212  * will be called with data as the argument, when milliseconds into the
00213  * future (approximately)
00214  * If callback returns 0, no further events will be re-scheduled
00215  * \return Returns a schedule item ID on success, -1 on failure
00216  */
00217 int ast_sched_add_variable(struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result;
00218 
00219 /*!
00220  * \brief replace a scheduler entry
00221  * \deprecated You should use the AST_SCHED_REPLACE_VARIABLE() macro instead.
00222  *
00223  * This deletes the scheduler entry for old_id if it exists, and then
00224  * calls ast_sched_add to create a new entry.  A negative old_id will
00225  * be ignored.
00226  *
00227  * \retval -1 failure
00228  * \retval otherwise, returns scheduled item ID
00229  */
00230 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;
00231 
00232    
00233 /*! 
00234  * \brief Find a sched structure and return the data field associated with it. 
00235  * \param con scheduling context in which to search fro the matching id
00236  * \param id ID of the scheduled item to find
00237  * \return the data field from the matching sched struct if found; else return NULL if not found.
00238  * \since 1.6.1
00239  */
00240 
00241 const void *ast_sched_find_data(struct sched_context *con, int id);
00242    
00243 /*! \brief Deletes a scheduled event
00244  * Remove this event from being run.  A procedure should not remove its own
00245  * event, but return 0 instead.  In most cases, you should not call this
00246  * routine directly, but use the AST_SCHED_DEL() macro instead (especially if
00247  * you don't intend to do something different when it returns failure).
00248  * \param con scheduling context to delete item from
00249  * \param id ID of the scheduled item to delete
00250  * \return Returns 0 on success, -1 on failure
00251  */
00252 #ifndef AST_DEVMODE
00253 int ast_sched_del(struct sched_context *con, int id) attribute_warn_unused_result;
00254 #else
00255 int _ast_sched_del(struct sched_context *con, int id, const char *file, int line, const char *function) attribute_warn_unused_result;
00256 #define  ast_sched_del(a, b)  _ast_sched_del(a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00257 #endif
00258 
00259 /*! \brief Determines number of seconds until the next outstanding event to take place
00260  * Determine the number of seconds until the next outstanding event
00261  * should take place, and return the number of milliseconds until
00262  * it needs to be run.  This value is perfect for passing to the poll
00263  * call.
00264  * \param con context to act upon
00265  * \return Returns "-1" if there is nothing there are no scheduled events
00266  * (and thus the poll should not timeout)
00267  */
00268 int ast_sched_wait(struct sched_context *con) attribute_warn_unused_result;
00269 
00270 /*! \brief Runs the queue
00271  * \param con Scheduling context to run
00272  * Run the queue, executing all callbacks which need to be performed
00273  * at this time.
00274  * \param con context to act upon
00275  * \return Returns the number of events processed.
00276  */
00277 int ast_sched_runq(struct sched_context *con);
00278 
00279 /*! \brief Dumps the scheduler contents
00280  * Debugging: Dump the contents of the scheduler to stderr
00281  * \param con Context to dump
00282  */
00283 void ast_sched_dump(struct sched_context *con);
00284 
00285 /*! \brief Returns the number of seconds before an event takes place
00286  * \param con Context to use
00287  * \param id Id to dump
00288  */
00289 long ast_sched_when(struct sched_context *con,int id);
00290 
00291 /*!
00292  * \brief Convenience macro for objects and reference (add)
00293  *
00294  */
00295 #define ast_sched_add_object(obj,con,when,callback) ast_sched_add((con),(when),(callback), ASTOBJ_REF((obj)))
00296 
00297 /*!
00298  * \brief Convenience macro for objects and reference (del)
00299  *
00300  */
00301 #define ast_sched_del_object(obj,destructor,con,id) do { \
00302    if ((id) > -1) { \
00303       ast_sched_del((con),(id)); \
00304       (id) = -1; \
00305       ASTOBJ_UNREF((obj),(destructor)); \
00306    } \
00307 } while(0)
00308 
00309 /*!
00310  * \brief An opaque type representing a scheduler thread
00311  *
00312  * The purpose of the ast_sched_thread API is to provide a common implementation
00313  * of the case where a module wants to have a dedicated thread for handling the
00314  * scheduler.
00315  */
00316 struct ast_sched_thread;
00317 
00318 /*!
00319  * \brief Create a scheduler with a dedicated thread
00320  *
00321  * This function should be used to allocate a scheduler context and a dedicated
00322  * thread for processing scheduler entries.  The thread is started immediately.
00323  *
00324  * \retval NULL error
00325  * \retval non-NULL a handle to the scheduler and its dedicated thread.
00326  */
00327 struct ast_sched_thread *ast_sched_thread_create(void);
00328 
00329 /*!
00330  * \brief Destroy a scheduler and its thread
00331  *
00332  * This function is used to destroy a scheduler context and the dedicated thread
00333  * that was created for handling scheduler entries.  Any entries in the scheduler
00334  * that have not yet been processed will be thrown away.  Once this function is
00335  * called, the handle must not be used again.
00336  *
00337  * \param st the handle to the scheduler and thread
00338  *
00339  * \return NULL for convenience
00340  */
00341 struct ast_sched_thread *ast_sched_thread_destroy(struct ast_sched_thread *st);
00342 
00343 /*!
00344  * \brief Add a scheduler entry
00345  *
00346  * \param st the handle to the scheduler and thread
00347  * \param when the number of ms in the future to run the task.  A value <= 0
00348  *        is treated as "run now".
00349  * \param cb the function to call when the scheduled time arrives
00350  * \param data the parameter to pass to the scheduler callback
00351  *
00352  * \retval -1 Failure
00353  * \retval >=0 Sched ID of added task
00354  */
00355 int ast_sched_thread_add(struct ast_sched_thread *st, int when, ast_sched_cb cb,
00356       const void *data);
00357 
00358 /*!
00359  * \brief Add a variable reschedule time scheduler entry
00360  *
00361  * \param st the handle to the scheduler and thread
00362  * \param when the number of ms in the future to run the task.  A value <= 0
00363  *        is treated as "run now".
00364  * \param cb the function to call when the scheduled time arrives
00365  * \param data the parameter to pass to the scheduler callback
00366  * \param variable If this value is non-zero, then the scheduler will use the return
00367  *        value of the scheduler as the amount of time in the future to run the
00368  *        task again.  Normally, a return value of 0 means do not re-schedule, and
00369  *        non-zero means re-schedule using the time provided when the scheduler
00370  *        entry was first created.
00371  *
00372  * \retval -1 Failure
00373  * \retval >=0 Sched ID of added task
00374  */
00375 int ast_sched_thread_add_variable(struct ast_sched_thread *st, int when, ast_sched_cb cb,
00376       const void *data, int variable);
00377 
00378 /*!
00379  * \brief Get the scheduler context for a given ast_sched_thread
00380  *
00381  * This function should be used only when direct access to the scheduler context
00382  * is required.  Its use is discouraged unless necessary.  The cases where 
00383  * this is currently required is when you want to take advantage of one of the 
00384  * AST_SCHED macros.
00385  *
00386  * \param st the handle to the scheduler and thread
00387  *
00388  * \return the sched_context associated with an ast_sched_thread
00389  */
00390 struct sched_context *ast_sched_thread_get_context(struct ast_sched_thread *st);
00391 
00392 /*!
00393  * \brief Delete a scheduler entry
00394  *
00395  * This uses the AST_SCHED_DEL macro internally.
00396  *
00397  * \param st the handle to the scheduler and thread
00398  * \param id scheduler entry id to delete
00399  *
00400  * \retval 0 success
00401  * \retval non-zero failure
00402  */
00403 #define ast_sched_thread_del(st, id) ({ \
00404    struct sched_context *__tmp_context = ast_sched_thread_get_context(st); \
00405    AST_SCHED_DEL(__tmp_context, id); \
00406 })
00407 
00408 /*!
00409  * \brief Force re-processing of the scheduler context
00410  *
00411  * \param st the handle to the scheduler and thread
00412  *
00413  * \return nothing
00414  */
00415 void ast_sched_thread_poke(struct ast_sched_thread *st);
00416 
00417 #if defined(__cplusplus) || defined(c_plusplus)
00418 }
00419 #endif
00420 
00421 #endif /* _ASTERISK_SCHED_H */

Generated on Sat Mar 10 01:54:26 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7