Commit ed7295aa authored by Marek Vavrusa's avatar Marek Vavrusa

Event scheduler cancellation now waits for currently running event.

parent 1537f0e5
......@@ -39,6 +39,7 @@ evsched_t *evsched_new()
}
/* Initialize event calendar. */
pthread_mutex_init(&s->rl, 0);
pthread_mutex_init(&s->mx, 0);
pthread_cond_init(&s->notify, 0);
pthread_mutex_init(&s->cache.lock, 0);
......@@ -57,6 +58,7 @@ void evsched_delete(evsched_t **s)
}
/* Deinitialize event calendar. */
pthread_mutex_destroy(&(*s)->rl);
pthread_mutex_destroy(&(*s)->mx);
pthread_cond_destroy(&(*s)->notify);
node *n = 0, *nxt = 0;
......@@ -126,6 +128,8 @@ event_t* evsched_next(evsched_t *s)
/* Immediately return. */
if (timercmp(&dt, &next_ev->tv, >=)) {
rem_node(&next_ev->n);
pthread_mutex_lock(&s->rl);
s->current = next_ev;
pthread_mutex_unlock(&s->mx);
return next_ev;
}
......@@ -147,6 +151,23 @@ event_t* evsched_next(evsched_t *s)
}
int evsched_event_finished(evsched_t *s)
{
if (!s) {
return -1;
}
/* Mark as finished. */
if (s->current) {
s->current = 0;
pthread_mutex_unlock(&s->rl);
return 0;
}
/* Finished event is not current. */
return -1;
}
int evsched_schedule(evsched_t *s, event_t *ev, uint32_t dt)
{
if (!s || !ev || dt < 0) {
......@@ -239,9 +260,15 @@ int evsched_cancel(evsched_t *s, event_t *ev)
/* Lock calendar. */
pthread_mutex_lock(&s->mx);
/* Make sure not running. */
pthread_mutex_lock(&s->rl);
/* Remove from list. */
rem_node(&ev->n);
/* Enable running events. */
pthread_mutex_unlock(&s->rl);
/* Unlock calendar. */
pthread_cond_signal(&s->notify);
pthread_mutex_unlock(&s->mx);
......
......@@ -73,6 +73,8 @@ typedef enum evsched_ev_t {
* Scheduler is terminated with a special EVSCHED_TERM event type.
*/
typedef struct {
pthread_mutex_t rl; /*!< Event running lock. */
event_t *current; /*!< Current running event. */
pthread_mutex_t mx; /*!< Event queue locking. */
pthread_cond_t notify; /*!< Event queue notification. */
list calendar; /*!< Event calendar. */
......@@ -122,6 +124,8 @@ void evsched_event_free(evsched_t *s, event_t *ev);
* Scheduler may block until a next event is available.
* Send scheduler an EVSCHED_NOOP or EVSCHED_TERM event to unblock it.
*
* \warning Returned event must be marked as finished, or deadlock occurs.
*
* \param s Event scheduler.
*
* \retval Scheduled event.
......@@ -129,6 +133,18 @@ void evsched_event_free(evsched_t *s, event_t *ev);
*/
event_t* evsched_next(evsched_t *s);
/*!
* \brief Mark running event as finished.
*
* Need to call this after each event returned by evsched_next() is finished.
*
* \param s Event scheduler.
*
* \retval 0 if successful.
* \retval -1 on errors.
*/
int evsched_event_finished(evsched_t *s);
/*!
* \brief Schedule an event.
*
......@@ -172,6 +188,12 @@ event_t* evsched_schedule_term(evsched_t *s, uint32_t dt);
/*!
* \brief Cancel a scheduled event.
*
* \warning May block until current running event is finished (as it cannot
* interrupt running event).
*
* \warning Never cancel event in it's callback. As it never finishes,
* it deadlocks.
*
* \param s Event scheduler.
* \param ev Scheduled event.
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment