summaryrefslogtreecommitdiff
path: root/src/common/evsched.h
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-11-02 22:44:12 +0100
committerOndřej Surý <ondrej@sury.org>2011-11-02 22:44:12 +0100
commitc8d5977bb546dae9ed59d81556639c49badd8121 (patch)
tree4c86750db26c1c3502b60f2cd78ca9611cfa01d6 /src/common/evsched.h
downloadknot-c8d5977bb546dae9ed59d81556639c49badd8121.tar.gz
Imported Upstream version 0.8.0~pre1upstream/0.8.0_pre1
Diffstat (limited to 'src/common/evsched.h')
-rw-r--r--src/common/evsched.h240
1 files changed, 240 insertions, 0 deletions
diff --git a/src/common/evsched.h b/src/common/evsched.h
new file mode 100644
index 0000000..2a682e1
--- /dev/null
+++ b/src/common/evsched.h
@@ -0,0 +1,240 @@
+/* Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*!
+ * \file evsched.h
+ *
+ * \author Marek Vavrusa <marek.vavrusa@nic.cz>
+ *
+ * \brief Event scheduler.
+ *
+ * Scheduler works with the same event_t type as event queue.
+ * It is also thread-safe so the scheduler can run in a separate thread
+ * while events can be enqueued from different threads.
+ *
+ * Guideline is, that the scheduler run loop should exit with
+ * a special event type EVSCHED_TERM.
+ *
+ * Example usage:
+ * \code
+ * evsched_t *s = evsched_new();
+ *
+ * // Schedule myfunc() after 1000ms
+ * evsched_schedule_cb(s, myfunc, data, 1000)
+ *
+ * // Schedule termination event after 1500ms
+ * evsched_schedule_term(s, 1500);
+ *
+ * // Event scheduler main loop
+ * while (1) {
+ * // Wait for next scheduled event
+ * event_t *ev = evsched_next();
+ *
+ * // Break on termination event
+ * if (ev->type == EVSCHED_TERM) {
+ * evsched_event_free(s, ev);
+ * break;
+ * }
+ *
+ * // Execute and discard event
+ * if (ev->cb) {
+ * ev->cb(ev);
+ * }
+ * evsched_event_free(s, ev); // Free executed event
+ * }
+ *
+ * // Delete event scheduler
+ * evsched_delete(s);
+ * \endcode
+ *
+ * \addtogroup common_lib
+ * @{
+ */
+
+#ifndef _KNOTD_COMMON_EVSCHED_H_
+#define _KNOTD_COMMON_EVSCHED_H_
+
+#include <pthread.h>
+#include "common/slab/slab.h"
+#include "common/lists.h"
+#include "common/evqueue.h"
+
+/*!
+ * \brief Scheduler event types.
+ */
+typedef enum evsched_ev_t {
+ EVSCHED_NOOP = 0, /*!< No-op action, skip. */
+ EVSCHED_CB, /*!< Callback action. */
+ EVSCHED_TERM /*!< Terminal action, stop event scheduler. */
+} evsched_ev_t;
+
+/*!
+ * \brief Event scheduler structure.
+ *
+ * Keeps list of scheduled events. Events are executed in their scheduled
+ * time and kept in an ordered list (queue).
+ * 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. */
+ struct {
+ slab_cache_t alloc; /*!< Events SLAB cache. */
+ pthread_mutex_t lock; /*!< Events cache spin lock. */
+ } cache;
+} evsched_t;
+
+/*!
+ * \brief Create new event scheduler instance.
+ *
+ * \retval New instance on success.
+ * \retval NULL on error.
+ */
+evsched_t *evsched_new();
+
+/*!
+ * \brief Deinitialize and free event scheduler instance.
+ *
+ * \param s Pointer to event scheduler instance.
+ * \note *sched is set to 0.
+ */
+void evsched_delete(evsched_t **s);
+
+/*!
+ * \brief Create an empty event.
+ *
+ * \param s Pointer to event scheduler instance.
+ * \param type Event type.
+ * \retval New instance on success.
+ * \retval NULL on error.
+ */
+event_t *evsched_event_new(evsched_t *s, int type);
+
+/*!
+ * \brief Dispose event instance.
+ *
+ * \param s Pointer to event scheduler instance.
+ * \param ev Event instance.
+ */
+void evsched_event_free(evsched_t *s, event_t *ev);
+
+/*!
+ * \brief Fetch next-event.
+ *
+ * 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.
+ * \retval NULL on error.
+ */
+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.
+ *
+ * \param s Event scheduler.
+ * \param ev Prepared event.
+ * \param dt Time difference in milliseconds from now (dt is relative).
+ *
+ * \retval 0 on success.
+ * \retval <0 on error.
+ */
+int evsched_schedule(evsched_t *s, event_t *ev, uint32_t dt);
+
+/*!
+ * \brief Schedule callback event.
+ *
+ * Execute callback after dt miliseconds has passed.
+ *
+ * \param s Event scheduler.
+ * \param cb Callback handler.
+ * \param data Data for callback.
+ * \param dt Time difference in milliseconds from now (dt is relative).
+ *
+ * \retval Event instance on success.
+ * \retval NULL on error.
+ */
+event_t* evsched_schedule_cb(evsched_t *s, event_cb_t cb, void *data, uint32_t dt);
+
+/*!
+ * \brief Schedule termination event.
+ *
+ * Special action for scheduler termination.
+ *
+ * \param s Event scheduler.
+ * \param dt Time difference in milliseconds from now (dt is relative).
+ *
+ * \retval Event instance on success.
+ * \retval NULL on error.
+ */
+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.
+ *
+ * \retval 0 on success.
+ * \retval <0 on error.
+ */
+int evsched_cancel(evsched_t *s, event_t *ev);
+
+/* Singleton event scheduler pointer. */
+extern evsched_t *s_evsched;
+
+/*!
+ * \brief Event scheduler singleton.
+ */
+static inline evsched_t *evsched() {
+ return s_evsched;
+}
+
+/*!
+ * \brief Set event scheduler singleton.
+ */
+static inline void evsched_set(evsched_t *s) {
+ s_evsched = s;
+}
+
+
+#endif /* _KNOTD_COMMON_EVSCHED_H_ */
+
+/*! @} */