Note! This project has moved to github.com/armmbed/mbed-events

Dependents:   SimpleHTTPExample

This repository has been superceded

This project has moved to mbed-events

Composable event loops combine the cheap synchronicity of event loops with the composability of preempted threads.

Two modular event queue classes are provided:

  • EventLoop - for loops coupled with a c++ managed thread
  • EventQueue - for manually managed event queues

The Event class takes advantage of the extensibility of FuncPtr to allow an event to be passed through APIs as a normal function.

More information on composable event loops.

Revision:
17:6d564266850e
Parent:
16:ff5d48fcce1b
Child:
18:765776145464
--- a/EventQueue.h	Mon Apr 18 09:47:21 2016 -0500
+++ b/EventQueue.h	Mon Apr 18 12:51:04 2016 -0500
@@ -54,14 +54,14 @@
         // data follows
     };
 
-    struct event *alloc(unsigned size, int ms=-1);
-    void dealloc(struct event *);
+    struct event *event_alloc(unsigned size, int ms=-1);
+    void event_dealloc(struct event *);
 
-    void trigger(struct event *e, int delay);
+    void event_trigger(struct event *e, int delay);
 
     template <typename F>
-    bool trigger(F func, int delay, int period, int tolerance, int ms=-1) {
-        struct event *e = alloc(sizeof(F), ms);
+    bool event_trigger(F func, int delay, int period, int tolerance, int ms=-1) {
+        struct event *e = event_alloc(sizeof(F), ms);
         if (!e) {
             return false;
         }
@@ -71,7 +71,7 @@
         e->dispatch = &F::thunk;
         *reinterpret_cast<F*>(e+1) = func;
 
-        trigger(e, delay);
+        event_trigger(e, delay);
         return true;
     }
 
@@ -88,6 +88,340 @@
 
     template <typename F>
     friend class Event;
+
+public:
+    // An event loop provides three additional convenience functions
+    // trigger       - Immediately post an event to the queue
+    // trigger_in    - Post an event after a specified time in milliseconds
+    // trigger_every - Post an event periodically in milliseconds
+    //
+    // Unfortunately, the lack of converting constructors in
+    // template functions combined with a lack of variadic
+    // templates requires 18 declarations for each function
+
+    /** Immediately post an event to the queue */
+    template <typename F, typename A0, typename A1, typename A2, typename A3, typename A4>
+    bool trigger(F func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
+        return event_trigger(Binder<void(A0,A1,A2,A3,A4),A0,A1,A2,A3,A4>(func,a0,a1,a2,a3,a4), 0, -1, 0);
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4>
+    bool trigger(T *obj, void (*func)(T*,A0,A1,A2,A3,A4), A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
+        return trigger(FuncPtr<void(A0,A1,A2,A3,A4)>(obj,func),a0,a1,a2,a3,a4);
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4>
+    bool trigger(T *obj, void (T::*func)(A0,A1,A2,A3,A4), A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
+        return trigger(FuncPtr<void(A0,A1,A2,A3,A4)>(obj,func),a0,a1,a2,a3,a4);
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename F, typename A0, typename A1, typename A2, typename A3>
+    bool trigger(F func, A0 a0, A1 a1, A2 a2, A3 a3) {
+        return event_trigger(Binder<void(A0,A1,A2,A3),A0,A1,A2,A3>(func,a0,a1,a2,a3), 0, -1, 0);
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename T, typename A0, typename A1, typename A2, typename A3>
+    bool trigger(T *obj, void (*func)(T*,A0,A1,A2,A3), A0 a0, A1 a1, A2 a2, A3 a3) {
+        return trigger(FuncPtr<void(A0,A1,A2,A3)>(obj,func),a0,a1,a2,a3);
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename T, typename A0, typename A1, typename A2, typename A3>
+    bool trigger(T *obj, void (T::*func)(A0,A1,A2,A3), A0 a0, A1 a1, A2 a2, A3 a3) {
+        return trigger(FuncPtr<void(A0,A1,A2,A3)>(obj,func),a0,a1,a2,a3);
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename F, typename A0, typename A1, typename A2>
+    bool trigger(F func, A0 a0, A1 a1, A2 a2) {
+        return event_trigger(Binder<void(A0,A1,A2),A0,A1,A2>(func,a0,a1,a2), 0, -1, 0);
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename T, typename A0, typename A1, typename A2>
+    bool trigger(T *obj, void (*func)(T*,A0,A1,A2), A0 a0, A1 a1, A2 a2) {
+        return trigger(FuncPtr<void(A0,A1,A2)>(obj,func),a0,a1,a2);
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename T, typename A0, typename A1, typename A2>
+    bool trigger(T *obj, void (T::*func)(A0,A1,A2), A0 a0, A1 a1, A2 a2) {
+        return trigger(FuncPtr<void(A0,A1,A2)>(obj,func),a0,a1,a2);
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename F, typename A0, typename A1>
+    bool trigger(F func, A0 a0, A1 a1) {
+        return event_trigger(Binder<void(A0,A1),A0,A1>(func,a0,a1), 0, -1, 0);
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename T, typename A0, typename A1>
+    bool trigger(T *obj, void (*func)(T*,A0,A1), A0 a0, A1 a1) {
+        return trigger(FuncPtr<void(A0,A1)>(obj,func),a0,a1);
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename T, typename A0, typename A1>
+    bool trigger(T *obj, void (T::*func)(A0,A1), A0 a0, A1 a1) {
+        return trigger(FuncPtr<void(A0,A1)>(obj,func),a0,a1);
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename F, typename A0>
+    bool trigger(F func, A0 a0) {
+        return event_trigger(Binder<void(A0),A0>(func,a0), 0, -1, 0);
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename T, typename A0>
+    bool trigger(T *obj, void (*func)(T*,A0), A0 a0) {
+        return trigger(FuncPtr<void(A0)>(obj,func),a0);
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename T, typename A0>
+    bool trigger(T *obj, void (T::*func)(A0), A0 a0) {
+        return trigger(FuncPtr<void(A0)>(obj,func),a0);
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename F>
+    bool trigger(F func) {
+        return event_trigger(Binder<void()>(func), 0, -1, 0);
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename T>
+    bool trigger(T *obj, void (*func)(T*)) {
+        return trigger(FuncPtr<void()>(obj,func));
+    }
+
+    /** Immediately post an event to the queue */
+    template <typename T>
+    bool trigger(T *obj, void (T::*func)()) {
+        return trigger(FuncPtr<void()>(obj,func));
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename F, typename A0, typename A1, typename A2, typename A3, typename A4>
+    bool trigger_in(F func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, int ms=-1) {
+        return event_trigger(Binder<void(A0,A1,A2,A3,A4),A0,A1,A2,A3,A4>(func,a0,a1,a2,a3,a4), ms, -1, 0);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4>
+    bool trigger_in(T *obj, void (*func)(T*,A0,A1,A2,A3,A4), A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, int ms=-1) {
+        return trigger_in(FuncPtr<void(A0,A1,A2,A3,A4)>(obj,func),a0,a1,a2,a3,a4,ms);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4>
+    bool trigger_in(T *obj, void (T::*func)(A0,A1,A2,A3,A4), A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, int ms=-1) {
+        return trigger_in(FuncPtr<void(A0,A1,A2,A3,A4)>(obj,func),a0,a1,a2,a3,a4,ms);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename F, typename A0, typename A1, typename A2, typename A3>
+    bool trigger_in(F func, A0 a0, A1 a1, A2 a2, A3 a3, int ms=-1) {
+        return event_trigger(Binder<void(A0,A1,A2,A3),A0,A1,A2,A3>(func,a0,a1,a2,a3), ms, -1, 0);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename T, typename A0, typename A1, typename A2, typename A3>
+    bool trigger_in(T *obj, void (*func)(T*,A0,A1,A2,A3), A0 a0, A1 a1, A2 a2, A3 a3, int ms=-1) {
+        return trigger_in(FuncPtr<void(A0,A1,A2,A3)>(obj,func),a0,a1,a2,a3,ms);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename T, typename A0, typename A1, typename A2, typename A3>
+    bool trigger_in(T *obj, void (T::*func)(A0,A1,A2,A3), A0 a0, A1 a1, A2 a2, A3 a3, int ms=-1) {
+        return trigger_in(FuncPtr<void(A0,A1,A2,A3)>(obj,func),a0,a1,a2,a3,ms);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename F, typename A0, typename A1, typename A2>
+    bool trigger_in(F func, A0 a0, A1 a1, A2 a2, int ms=-1) {
+        return event_trigger(Binder<void(A0,A1,A2),A0,A1,A2>(func,a0,a1,a2), ms, -1, 0);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename T, typename A0, typename A1, typename A2>
+    bool trigger_in(T *obj, void (*func)(T*,A0,A1,A2), A0 a0, A1 a1, A2 a2, int ms=-1) {
+        return trigger_in(FuncPtr<void(A0,A1,A2)>(obj,func),a0,a1,a2,ms);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename T, typename A0, typename A1, typename A2>
+    bool trigger_in(T *obj, void (T::*func)(A0,A1,A2), A0 a0, A1 a1, A2 a2, int ms=-1) {
+        return trigger_in(FuncPtr<void(A0,A1,A2)>(obj,func),a0,a1,a2,ms);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename F, typename A0, typename A1>
+    bool trigger_in(F func, A0 a0, A1 a1, int ms=-1) {
+        return event_trigger(Binder<void(A0,A1),A0,A1>(func,a0,a1), ms, -1, 0);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename T, typename A0, typename A1>
+    bool trigger_in(T *obj, void (*func)(T*,A0,A1), A0 a0, A1 a1, int ms=-1) {
+        return trigger_in(FuncPtr<void(A0,A1)>(obj,func),a0,a1,ms);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename T, typename A0, typename A1>
+    bool trigger_in(T *obj, void (T::*func)(A0,A1), A0 a0, A1 a1, int ms=-1) {
+        return trigger_in(FuncPtr<void(A0,A1)>(obj,func),a0,a1,ms);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename F, typename A0>
+    bool trigger_in(F func, A0 a0, int ms=-1) {
+        return event_trigger(Binder<void(A0),A0>(func,a0), ms, -1, 0);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename T, typename A0>
+    bool trigger_in(T *obj, void (*func)(T*,A0), A0 a0, int ms=-1) {
+        return trigger_in(FuncPtr<void(A0)>(obj,func),a0,ms);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename T, typename A0>
+    bool trigger_in(T *obj, void (T::*func)(A0), A0 a0, int ms=-1) {
+        return trigger_in(FuncPtr<void(A0)>(obj,func),a0,ms);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename F>
+    bool trigger_in(F func, int ms=-1) {
+        return event_trigger(Binder<void()>(func), ms, -1, 0);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename T>
+    bool trigger_in(T *obj, void (*func)(T*), int ms=-1) {
+        return trigger_in(FuncPtr<void()>(obj,func),ms);
+    }
+
+    /** Post an event after a specified time in milliseconds */
+    template <typename T>
+    bool trigger_in(T *obj, void (T::*func)(), int ms=-1) {
+        return trigger_in(FuncPtr<void()>(obj,func),ms);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename F, typename A0, typename A1, typename A2, typename A3, typename A4>
+    bool trigger_every(F func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, int ms=-1) {
+        return event_trigger(Binder<void(A0,A1,A2,A3,A4),A0,A1,A2,A3,A4>(func,a0,a1,a2,a3,a4), 0, ms, 0);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4>
+    bool trigger_every(T *obj, void (*func)(T*,A0,A1,A2,A3,A4), A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, int ms=-1) {
+        return trigger_every(FuncPtr<void(A0,A1,A2,A3,A4)>(obj,func),a0,a1,a2,a3,a4,ms);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4>
+    bool trigger_every(T *obj, void (T::*func)(A0,A1,A2,A3,A4), A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, int ms=-1) {
+        return trigger_every(FuncPtr<void(A0,A1,A2,A3,A4)>(obj,func),a0,a1,a2,a3,a4,ms);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename F, typename A0, typename A1, typename A2, typename A3>
+    bool trigger_every(F func, A0 a0, A1 a1, A2 a2, A3 a3, int ms=-1) {
+        return event_trigger(Binder<void(A0,A1,A2,A3),A0,A1,A2,A3>(func,a0,a1,a2,a3), 0, ms, 0);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename T, typename A0, typename A1, typename A2, typename A3>
+    bool trigger_every(T *obj, void (*func)(T*,A0,A1,A2,A3), A0 a0, A1 a1, A2 a2, A3 a3, int ms=-1) {
+        return trigger_every(FuncPtr<void(A0,A1,A2,A3)>(obj,func),a0,a1,a2,a3,ms);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename T, typename A0, typename A1, typename A2, typename A3>
+    bool trigger_every(T *obj, void (T::*func)(A0,A1,A2,A3), A0 a0, A1 a1, A2 a2, A3 a3, int ms=-1) {
+        return trigger_every(FuncPtr<void(A0,A1,A2,A3)>(obj,func),a0,a1,a2,a3,ms);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename F, typename A0, typename A1, typename A2>
+    bool trigger_every(F func, A0 a0, A1 a1, A2 a2, int ms=-1) {
+        return event_trigger(Binder<void(A0,A1,A2),A0,A1,A2>(func,a0,a1,a2), 0, ms, 0);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename T, typename A0, typename A1, typename A2>
+    bool trigger_every(T *obj, void (*func)(T*,A0,A1,A2), A0 a0, A1 a1, A2 a2, int ms=-1) {
+        return trigger_every(FuncPtr<void(A0,A1,A2)>(obj,func),a0,a1,a2,ms);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename T, typename A0, typename A1, typename A2>
+    bool trigger_every(T *obj, void (T::*func)(A0,A1,A2), A0 a0, A1 a1, A2 a2, int ms=-1) {
+        return trigger_every(FuncPtr<void(A0,A1,A2)>(obj,func),a0,a1,a2,ms);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename F, typename A0, typename A1>
+    bool trigger_every(F func, A0 a0, A1 a1, int ms=-1) {
+        return event_trigger(Binder<void(A0,A1),A0,A1>(func,a0,a1), 0, ms, 0);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename T, typename A0, typename A1>
+    bool trigger_every(T *obj, void (*func)(T*,A0,A1), A0 a0, A1 a1, int ms=-1) {
+        return trigger_every(FuncPtr<void(A0,A1)>(obj,func),a0,a1,ms);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename T, typename A0, typename A1>
+    bool trigger_every(T *obj, void (T::*func)(A0,A1), A0 a0, A1 a1, int ms=-1) {
+        return trigger_every(FuncPtr<void(A0,A1)>(obj,func),a0,a1,ms);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename F, typename A0>
+    bool trigger_every(F func, A0 a0, int ms=-1) {
+        return event_trigger(Binder<void(A0),A0>(func,a0), 0, ms, 0);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename T, typename A0>
+    bool trigger_every(T *obj, void (*func)(T*,A0), A0 a0, int ms=-1) {
+        return trigger_every(FuncPtr<void(A0)>(obj,func),a0,ms);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename T, typename A0>
+    bool trigger_every(T *obj, void (T::*func)(A0), A0 a0, int ms=-1) {
+        return trigger_every(FuncPtr<void(A0)>(obj,func),a0,ms);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename F>
+    bool trigger_every(F func, int ms=-1) {
+        return event_trigger(Binder<void()>(func), 0, ms, 0);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename T>
+    bool trigger_every(T *obj, void (*func)(T*), int ms=-1) {
+        return trigger_every(FuncPtr<void()>(obj,func),ms);
+    }
+
+    /** Post an event periodically in milliseconds */
+    template <typename T>
+    bool trigger_every(T *obj, void (T::*func)(), int ms=-1) {
+        return trigger_every(FuncPtr<void()>(obj,func),ms);
+    }
 };