[asterisk-commits] kmoore: branch kmoore/scheduler r410932 - in /team/kmoore/scheduler: include/...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Mar 19 10:27:27 CDT 2014


Author: kmoore
Date: Wed Mar 19 10:27:21 2014
New Revision: 410932

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=410932
Log:
Modify the scheduler API to be more sane

Modified:
    team/kmoore/scheduler/include/asterisk/sched.h
    team/kmoore/scheduler/main/sched.c

Modified: team/kmoore/scheduler/include/asterisk/sched.h
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/scheduler/include/asterisk/sched.h?view=diff&rev=410932&r1=410931&r2=410932
==============================================================================
--- team/kmoore/scheduler/include/asterisk/sched.h (original)
+++ team/kmoore/scheduler/include/asterisk/sched.h Wed Mar 19 10:27:21 2014
@@ -28,123 +28,6 @@
 extern "C" {
 #endif
 
-/*! 
- * \brief Remove a scheduler entry
- *
- * This is a loop construct to ensure that
- * the scheduled task get deleted. The idea is that
- * if we loop attempting to remove the scheduled task,
- * then whatever callback had been running will complete
- * and reinsert the task into the scheduler.
- *
- * Since macro expansion essentially works like pass-by-name
- * parameter passing, this macro will still work correctly even
- * if the id of the task to delete changes. This holds as long as 
- * the name of the id which could change is passed to the macro 
- * and not a copy of the value of the id.
- */
-#define AST_SCHED_DEL(sched, id) \
-	({ \
-		int _count = 0; \
-		int _sched_res = -1; \
-		while (id > -1 && (_sched_res = ast_sched_del(sched, id)) && ++_count < 10) \
-			usleep(1); \
-		if (_count == 10) { \
-			ast_debug(3, "Unable to cancel schedule ID %d.\n", id); \
-		} \
-		id = -1; \
-		(_sched_res); \
-	})
-
-#define AST_SCHED_DEL_ACCESSOR(sched, obj, getter, setter) \
-	({ \
-		int _count = 0; \
-		int _sched_res = -1; \
-		while (getter(obj) > -1 && (_sched_res = ast_sched_del(sched, getter(obj))) && ++_count < 10) \
-			usleep(1); \
-		if (_count == 10) { \
-			ast_debug(3, "Unable to cancel schedule ID %d.\n", getter(obj)); \
-		} \
-		setter(obj, -1); \
-		(_sched_res); \
-	})
-
-/*!
- * \brief schedule task to get deleted and call unref function
- * \sa AST_SCHED_DEL
- * \since 1.6.1
- */
-#define AST_SCHED_DEL_UNREF(sched, id, refcall)			\
-	do { \
-		int _count = 0; \
-		while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \
-			usleep(1); \
-		} \
-		if (_count == 10) \
-			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__); \
-		if (id > -1) \
-			refcall; \
-		id = -1; \
-	} while (0);
-
-/*!
- * \brief schedule task to get deleted releasing the lock between attempts
- * \since 1.6.1
- */
-#define AST_SCHED_DEL_SPINLOCK(sched, id, lock) \
-	({ \
-		int _count = 0; \
-		int _sched_res = -1; \
-		while (id > -1 && (_sched_res = ast_sched_del(sched, id)) && ++_count < 10) { \
-			ast_mutex_unlock(lock); \
-			usleep(1); \
-			ast_mutex_lock(lock); \
-		} \
-		if (_count == 10) { \
-			ast_debug(3, "Unable to cancel schedule ID %d.\n", id); \
-		} \
-		id = -1; \
-		(_sched_res); \
-	})
-
-#define AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, variable) \
-	do { \
-		int _count = 0; \
-		while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \
-			usleep(1); \
-		} \
-		if (_count == 10) \
-			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__); \
-		id = ast_sched_add_variable(sched, when, callback, data, variable); \
-	} while (0);
-
-#define AST_SCHED_REPLACE(id, sched, when, callback, data) \
-		AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, 0)
-
-/*!
- * \note Not currently used in the source?
- * \since 1.6.1
- */
-#define AST_SCHED_REPLACE_VARIABLE_UNREF(id, sched, when, callback, data, variable, unrefcall, addfailcall, refcall) \
-	do { \
-		int _count = 0, _res=1;											 \
-		void *_data = (void *)ast_sched_find_data(sched, id);			\
-		while (id > -1 && (_res = ast_sched_del(sched, id) && _count++ < 10)) { \
-			usleep(1); \
-		} \
-		if (!_res && _data)							\
-			unrefcall;	/* should ref _data! */		\
-		if (_count == 10) \
-			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__); \
-		refcall; \
-		id = ast_sched_add_variable(sched, when, callback, data, variable); \
-		if (id == -1)  \
-			addfailcall;	\
-	} while (0);
-
-#define AST_SCHED_REPLACE_UNREF(id, sched, when, callback, data, unrefcall, addfailcall, refcall) \
-	AST_SCHED_REPLACE_VARIABLE_UNREF(id, sched, when, callback, data, 0, unrefcall, addfailcall, refcall)
-
 /*!
  * \brief Create a scheduler context
  *
@@ -164,10 +47,12 @@
  *
  * A scheduler callback takes a pointer with callback data and
  *
+ * \param obj The data provided when the event was scheduled
+ *
  * \retval 0 if the callback should not be rescheduled
- * \retval non-zero if the callback should be scheduled agai
- */
-typedef int (*ast_sched_cb)(const void *data);
+ * \retval non-zero if the callback should be scheduled again
+ */
+typedef int (*ast_sched_cb)(void *obj);
 #define AST_SCHED_CB(a) ((ast_sched_cb)(a))
 
 struct ast_cb_names {
@@ -178,6 +63,7 @@
 
 /*!
  * \brief Show statics on what it is in the schedule queue
+ *
  * \param con Schedule context to check
  * \param buf dynamic string to store report
  * \param cbnames to check against
@@ -197,24 +83,11 @@
  * \param con Scheduler context to add
  * \param when how many milliseconds to wait for event to occur
  * \param callback function to call when the amount of time expires
- * \param data data to pass to the callback
+ * \param obj AO2 object to pass to the callback
  *
  * \return Returns a schedule item ID on success, -1 on failure
  */
-int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result;
-
-/*!
- * \brief replace a scheduler entry
- * \deprecated You should use the AST_SCHED_REPLACE() macro instead.
- *
- * This deletes the scheduler entry for old_id if it exists, and then
- * calls ast_sched_add to create a new entry.  A negative old_id will
- * be ignored.
- *
- * \retval -1 failure
- * \retval otherwise, returns scheduled item ID
- */
-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;
+#define ast_sched_add(con, when, callback, obj) ast_sched_add_variable(con, when, callback, obj, 0)
 
 /*!
  * \brief Adds a scheduled event with rescheduling support
@@ -222,7 +95,7 @@
  * \param con Scheduler context to add
  * \param when how many milliseconds to wait for event to occur
  * \param callback function to call when the amount of time expires
- * \param data data to pass to the callback
+ * \param obj AO2 object to pass to the callback
  * \param variable If true, the result value of callback function will be
  *       used for rescheduling
  *
@@ -234,39 +107,28 @@
  *
  * \return Returns a schedule item ID on success, -1 on failure
  */
-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;
-
-/*!
- * \brief replace a scheduler entry
- * \deprecated You should use the AST_SCHED_REPLACE_VARIABLE() macro instead.
- *
- * This deletes the scheduler entry for old_id if it exists, and then
- * calls ast_sched_add to create a new entry.  A negative old_id will
- * be ignored.
- *
- * \retval -1 failure
- * \retval otherwise, returns scheduled item ID
- */
-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;
+int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, void *obj, int variable) attribute_warn_unused_result;
 
 /*! 
  * \brief Find a sched structure and return the data field associated with it. 
+ * \since 1.6.1
  *
  * \param con scheduling context in which to search fro the matching id
  * \param id ID of the scheduled item to find
- * \return the data field from the matching sched struct if found; else return NULL if not found.
- *
- * \since 1.6.1
- */
-const void *ast_sched_find_data(struct ast_sched_context *con, int id);
+ *
+ * \return the AO2 object from the matching scheduled event (must be ao2_cleanup()d)
+ * \return NULL if not found or object not provided
+ */
+void *ast_sched_find_data(struct ast_sched_context *con, int id);
 
 /*!
  * \brief Deletes a scheduled event
  *
- * Remove this event from being run.  A procedure should not remove its own
- * event, but return 0 instead.  In most cases, you should not call this
- * routine directly, but use the AST_SCHED_DEL() macro instead (especially if
- * you don't intend to do something different when it returns failure).
+ * Remove this event from being run. A procedure should not remove its own
+ * event, but return 0 instead.
+ *
+ * The caller must not hold locks that the callback acquires when attempting
+ * to delete the scheduled event. This call is blocking on callback execution.
  *
  * \param con scheduling context to delete item from
  * \param id ID of the scheduled item to delete
@@ -326,24 +188,6 @@
 long ast_sched_when(struct ast_sched_context *con,int id);
 
 /*!
- * \brief Convenience macro for objects and reference (add)
- *
- */
-#define ast_sched_add_object(obj,con,when,callback) ast_sched_add((con),(when),(callback), ASTOBJ_REF((obj)))
-
-/*!
- * \brief Convenience macro for objects and reference (del)
- *
- */
-#define ast_sched_del_object(obj,destructor,con,id) do { \
-	if ((id) > -1) { \
-		ast_sched_del((con),(id)); \
-		(id) = -1; \
-		ASTOBJ_UNREF((obj),(destructor)); \
-	} \
-} while(0)
-
-/*!
  * \brief Start a thread for processing scheduler entries
  *
  * \param con the scheduler context this thread will manage

Modified: team/kmoore/scheduler/main/sched.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/scheduler/main/sched.c?view=diff&rev=410932&r1=410931&r2=410932
==============================================================================
--- team/kmoore/scheduler/main/sched.c (original)
+++ team/kmoore/scheduler/main/sched.c Wed Mar 19 10:27:21 2014
@@ -68,7 +68,7 @@
 	struct timeval when;          /*!< Absolute time event should take place */
 	int resched;                  /*!< When to reschedule */
 	int variable;                 /*!< Use return value from callback to reschedule */
-	const void *data;             /*!< Data */
+	void *object;                 /*!< AO2 object for callback */
 	ast_sched_cb callback;        /*!< Callback */
 	ssize_t __heap_index;
 };
@@ -261,6 +261,8 @@
 	 * Add to the cache, or just free() if we
 	 * already have too many cache entries
 	 */
+	ao2_cleanup(tmp->obj);
+	tmp->obj = NULL;
 
 #ifdef SCHED_MAX_CACHE
 	if (con->schedccnt < SCHED_MAX_CACHE) {
@@ -341,7 +343,7 @@
 /*! \brief
  * Schedule callback(data) to happen when ms into the future
  */
-int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable)
+int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, void *obj, int variable)
 {
 	struct sched *tmp;
 	int res = -1;
@@ -352,7 +354,7 @@
 	if ((tmp = sched_alloc(con))) {
 		tmp->id = con->eventcnt++;
 		tmp->callback = callback;
-		tmp->data = data;
+		tmp->object = ao2_bump(obj);
 		tmp->resched = when;
 		tmp->variable = variable;
 		tmp->when = ast_tv(0, 0);
@@ -415,7 +417,7 @@
 
 	s = sched_find(con, id);
 	if (s) {
-		data = s->data;
+		data = ao2_bump(s->object);
 	}
 
 	ast_mutex_unlock(&con->lock);
@@ -547,7 +549,7 @@
 		ast_debug(1, "|%.4d | %-15p | %-15p | %.6ld : %.6ld |\n",
 			q->id,
 			q->callback,
-			q->data,
+			q->object,
 			(long)delta.tv_sec,
 			(long int)delta.tv_usec);
 	}
@@ -591,10 +593,7 @@
 		 * should return 0.
 		 */
 
-		ast_mutex_unlock(&con->lock);
-		res = current->callback(current->data);
-		ast_mutex_lock(&con->lock);
-
+		res = current->callback(current->object);
 		if (res) {
 			/*
 			 * If they return non-zero, we should schedule them to be




More information about the asterisk-commits mailing list