Sat Feb 11 06:33:23 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 - 2010, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  * Russell Bryant <russell@digium.com>
00008  *
00009  * See http://www.asterisk.org for more information about
00010  * the Asterisk project. Please do not directly contact
00011  * any of the maintainers of this project for assistance;
00012  * the project provides a web site, mailing lists and IRC
00013  * channels for your use.
00014  *
00015  * This program is free software, distributed under the terms of
00016  * the GNU General Public License Version 2. See the LICENSE file
00017  * at the top of the source tree.
00018  */
00019 
00020 /*! \file
00021  * \brief Scheduler Routines (derived from cheops)
00022  */
00023 
00024 #ifndef _ASTERISK_SCHED_H
00025 #define _ASTERISK_SCHED_H
00026 
00027 #if defined(__cplusplus) || defined(c_plusplus)
00028 extern "C" {
00029 #endif
00030 
00031 /*! 
00032  * \brief Remove a scheduler entry
00033  *
00034  * This is a loop construct to ensure that
00035  * the scheduled task get deleted. The idea is that
00036  * if we loop attempting to remove the scheduled task,
00037  * then whatever callback had been running will complete
00038  * and reinsert the task into the scheduler.
00039  *
00040  * Since macro expansion essentially works like pass-by-name
00041  * parameter passing, this macro will still work correctly even
00042  * if the id of the task to delete changes. This holds as long as 
00043  * the name of the id which could change is passed to the macro 
00044  * and not a copy of the value of the id.
00045  */
00046 #define AST_SCHED_DEL(sched, id) \
00047    ({ \
00048       int _count = 0; \
00049       int _sched_res = -1; \
00050       while (id > -1 && (_sched_res = ast_sched_del(sched, id)) && ++_count < 10) \
00051          usleep(1); \
00052       if (_count == 10) { \
00053          ast_debug(3, "Unable to cancel schedule ID %d.\n", id); \
00054       } \
00055       id = -1; \
00056       (_sched_res); \
00057    })
00058 
00059 /*!
00060  * \brief schedule task to get deleted and call unref function
00061  * \sa AST_SCHED_DEL
00062  * \since 1.6.1
00063  */
00064 #define AST_SCHED_DEL_UNREF(sched, id, refcall)       \
00065    do { \
00066       int _count = 0; \
00067       while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \
00068          usleep(1); \
00069       } \
00070       if (_count == 10) \
00071          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__); \
00072       if (id > -1) \
00073          refcall; \
00074       id = -1; \
00075    } while (0);
00076 
00077 /*!
00078  * \brief schedule task to get deleted releasing the lock between attempts
00079  * \since 1.6.1
00080  */
00081 #define AST_SCHED_DEL_SPINLOCK(sched, id, lock) \
00082    ({ \
00083       int _count = 0; \
00084       int _sched_res = -1; \
00085       while (id > -1 && (_sched_res = ast_sched_del(sched, id)) && ++_count < 10) { \
00086          ast_mutex_unlock(lock); \
00087          usleep(1); \
00088          ast_mutex_lock(lock); \
00089       } \
00090       if (_count == 10) { \
00091          ast_debug(3, "Unable to cancel schedule ID %d.\n", id); \
00092       } \
00093       id = -1; \
00094       (_sched_res); \
00095    })
00096 
00097 #define AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, variable) \
00098    do { \
00099       int _count = 0; \
00100       while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \
00101          usleep(1); \
00102       } \
00103       if (_count == 10) \
00104          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__); \
00105       id = ast_sched_add_variable(sched, when, callback, data, variable); \
00106    } while (0);
00107 
00108 #define AST_SCHED_REPLACE(id, sched, when, callback, data) \
00109       AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, 0)
00110 
00111 /*!
00112  * \note Not currently used in the source?
00113  * \since 1.6.1
00114  */
00115 #define AST_SCHED_REPLACE_VARIABLE_UNREF(id, sched, when, callback, data, variable, unrefcall, addfailcall, refcall) \
00116    do { \
00117       int _count = 0, _res=1;                                \
00118       void *_data = (void *)ast_sched_find_data(sched, id);       \
00119       while (id > -1 && (_res = ast_sched_del(sched, id) && _count++ < 10)) { \
00120          usleep(1); \
00121       } \
00122       if (!_res && _data)                    \
00123          unrefcall;  /* should ref _data! */    \
00124       if (_count == 10) \
00125          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__); \
00126       refcall; \
00127       id = ast_sched_add_variable(sched, when, callback, data, variable); \
00128       if (id == -1)  \
00129          addfailcall;   \
00130    } while (0);
00131 
00132 #define AST_SCHED_REPLACE_UNREF(id, sched, when, callback, data, unrefcall, addfailcall, refcall) \
00133    AST_SCHED_REPLACE_VARIABLE_UNREF(id, sched, when, callback, data, 0, unrefcall, addfailcall, refcall)
00134 
00135 /*!
00136  * \brief Create a scheduler context
00137  *
00138  * \return Returns a malloc'd sched_context structure, NULL on failure
00139  */
00140 struct ast_sched_context *ast_sched_context_create(void);
00141 
00142 /*!
00143  * \brief destroys a schedule context
00144  *
00145  * \param c Context to free
00146  */
00147 void ast_sched_context_destroy(struct ast_sched_context *c);
00148 
00149 /*!
00150  * \brief scheduler callback
00151  *
00152  * A scheduler callback takes a pointer with callback data and
00153  *
00154  * \retval 0 if the callback should not be rescheduled
00155  * \retval non-zero if the callback should be scheduled agai
00156  */
00157 typedef int (*ast_sched_cb)(const void *data);
00158 #define AST_SCHED_CB(a) ((ast_sched_cb)(a))
00159 
00160 struct ast_cb_names {
00161    int numassocs;
00162    char *list[10];
00163    ast_sched_cb cblist[10];
00164 };
00165 
00166 /*!
00167  * \brief Show statics on what it is in the schedule queue
00168  * \param con Schedule context to check
00169  * \param buf dynamic string to store report
00170  * \param cbnames to check against
00171  * \since 1.6.1
00172  */
00173 void ast_sched_report(struct ast_sched_context *con, struct ast_str **buf, struct ast_cb_names *cbnames);
00174 
00175 /*!
00176  * \brief Adds a scheduled event
00177  *
00178  * Schedule an event to take place at some point in the future.  callback
00179  * will be called with data as the argument, when milliseconds into the
00180  * future (approximately)
00181  *
00182  * If callback returns 0, no further events will be re-scheduled
00183  *
00184  * \param con Scheduler context to add
00185  * \param when how many milliseconds to wait for event to occur
00186  * \param callback function to call when the amount of time expires
00187  * \param data data to pass to the callback
00188  *
00189  * \return Returns a schedule item ID on success, -1 on failure
00190  */
00191 int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result;
00192 
00193 /*!
00194  * \brief replace a scheduler entry
00195  * \deprecated You should use the AST_SCHED_REPLACE() macro instead.
00196  *
00197  * This deletes the scheduler entry for old_id if it exists, and then
00198  * calls ast_sched_add to create a new entry.  A negative old_id will
00199  * be ignored.
00200  *
00201  * \retval -1 failure
00202  * \retval otherwise, returns scheduled item ID
00203  */
00204 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;
00205 
00206 /*!
00207  * \brief Adds a scheduled event with rescheduling support
00208  *
00209  * \param con Scheduler context to add
00210  * \param when how many milliseconds to wait for event to occur
00211  * \param callback function to call when the amount of time expires
00212  * \param data data to pass to the callback
00213  * \param variable If true, the result value of callback function will be
00214  *       used for rescheduling
00215  *
00216  * Schedule an event to take place at some point in the future.  Callback
00217  * will be called with data as the argument, when milliseconds into the
00218  * future (approximately)
00219  *
00220  * If callback returns 0, no further events will be re-scheduled
00221  *
00222  * \return Returns a schedule item ID on success, -1 on failure
00223  */
00224 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;
00225 
00226 /*!
00227  * \brief replace a scheduler entry
00228  * \deprecated You should use the AST_SCHED_REPLACE_VARIABLE() macro instead.
00229  *
00230  * This deletes the scheduler entry for old_id if it exists, and then
00231  * calls ast_sched_add to create a new entry.  A negative old_id will
00232  * be ignored.
00233  *
00234  * \retval -1 failure
00235  * \retval otherwise, returns scheduled item ID
00236  */
00237 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;
00238 
00239 /*! 
00240  * \brief Find a sched structure and return the data field associated with it. 
00241  *
00242  * \param con scheduling context in which to search fro the matching id
00243  * \param id ID of the scheduled item to find
00244  * \return the data field from the matching sched struct if found; else return NULL if not found.
00245  *
00246  * \since 1.6.1
00247  */
00248 const void *ast_sched_find_data(struct ast_sched_context *con, int id);
00249 
00250 /*!
00251  * \brief Deletes a scheduled event
00252  *
00253  * Remove this event from being run.  A procedure should not remove its own
00254  * event, but return 0 instead.  In most cases, you should not call this
00255  * routine directly, but use the AST_SCHED_DEL() macro instead (especially if
00256  * you don't intend to do something different when it returns failure).
00257  *
00258  * \param con scheduling context to delete item from
00259  * \param id ID of the scheduled item to delete
00260  *
00261  * \return Returns 0 on success, -1 on failure
00262  */
00263 #ifndef AST_DEVMODE
00264 int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result;
00265 #else
00266 int _ast_sched_del(struct ast_sched_context *con, int id, const char *file, int line, const char *function) attribute_warn_unused_result;
00267 #define  ast_sched_del(a, b)  _ast_sched_del(a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00268 #endif
00269 
00270 /*!
00271  * \brief Determines number of seconds until the next outstanding event to take place
00272  *
00273  * Determine the number of seconds until the next outstanding event
00274  * should take place, and return the number of milliseconds until
00275  * it needs to be run.  This value is perfect for passing to the poll
00276  * call.
00277  *
00278  * \param con context to act upon
00279  *
00280  * \return Returns "-1" if there is nothing there are no scheduled events
00281  * (and thus the poll should not timeout)
00282  */
00283 int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result;
00284 
00285 /*!
00286  * \brief Runs the queue
00287  *
00288  * Run the queue, executing all callbacks which need to be performed
00289  * at this time.
00290  *
00291  * \param con Scheduling context to run
00292  * \param con context to act upon
00293  *
00294  * \return Returns the number of events processed.
00295  */
00296 int ast_sched_runq(struct ast_sched_context *con);
00297 
00298 /*!
00299  * \brief Dumps the scheduler contents
00300  *
00301  * Debugging: Dump the contents of the scheduler to stderr
00302  *
00303  * \param con Context to dump
00304  */
00305 void ast_sched_dump(struct ast_sched_context *con);
00306 
00307 /*!
00308  * \brief Returns the number of seconds before an event takes place
00309  *
00310  * \param con Context to use
00311  * \param id Id to dump
00312  */
00313 long ast_sched_when(struct ast_sched_context *con,int id);
00314 
00315 /*!
00316  * \brief Convenience macro for objects and reference (add)
00317  *
00318  */
00319 #define ast_sched_add_object(obj,con,when,callback) ast_sched_add((con),(when),(callback), ASTOBJ_REF((obj)))
00320 
00321 /*!
00322  * \brief Convenience macro for objects and reference (del)
00323  *
00324  */
00325 #define ast_sched_del_object(obj,destructor,con,id) do { \
00326    if ((id) > -1) { \
00327       ast_sched_del((con),(id)); \
00328       (id) = -1; \
00329       ASTOBJ_UNREF((obj),(destructor)); \
00330    } \
00331 } while(0)
00332 
00333 /*!
00334  * \brief Start a thread for processing scheduler entries
00335  *
00336  * \param con the scheduler context this thread will manage
00337  *
00338  * \retval 0 success
00339  * \retval non-zero failure
00340  */
00341 int ast_sched_start_thread(struct ast_sched_context *con);
00342 
00343 #if defined(__cplusplus) || defined(c_plusplus)
00344 }
00345 #endif
00346 
00347 #endif /* _ASTERISK_SCHED_H */

Generated on Sat Feb 11 06:33:23 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6