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:
14:5abf2ccf2dbf
Parent:
13:b84e049b2d9c
Child:
17:6d564266850e
--- a/Event.h	Fri Apr 22 22:32:35 2016 -0500
+++ b/Event.h	Tue May 10 07:51:44 2016 -0500
@@ -22,29 +22,21 @@
 public:
     /** Create an event bound to a queue
      */
-    Event(EventQueue *queue=0, FuncPtr<void(A0, A1, A2, A3, A4)> callback=0) {
-        memset(&_event, 0, sizeof _event);
-        _event.delay = 0;
-        _event.period = -1;
-        attach(queue, callback);
+    Event(EventQueue *queue=0, FuncPtr<void(A0, A1, A2, A3, A4)> func=0) {
+        _delay = 0;
+        _period = -1;
+        attach(queue, func);
     }
 
     /** Create an event bound to a queue
      */
     template <typename T, typename M>
     Event(EventQueue *queue, T *obj, M method) {
-        memset(&_event, 0, sizeof _event);
-        _event.delay = 0;
-        _event.period = -1;
+        _delay = 0;
+        _period = -1;
         attach(queue, obj, method);
     }
 
-    /** Safe lifetime management
-     */
-    ~Event() {
-        cancel();
-    }
-
     /** Attach an event to a queue
      */
     void attach(EventQueue *queue) {
@@ -53,8 +45,8 @@
 
     /** Attach a callback to an event
      */
-    void attach(FuncPtr<void(A0, A1, A2, A3, A4)> callback) {
-        _callback.attach(callback);
+    void attach(FuncPtr<void(A0, A1, A2, A3, A4)> func) {
+        _func.attach(func);
     }
 
     /** Attach a callback to an event
@@ -64,11 +56,11 @@
         attach(FuncPtr<void(A0, A1, A2, A3, A4)>(obj, method));
     }
 
-    /** Attach a callback to an event
+    /** Attach a func to an event
      */
-    void attach(EventQueue *queue, FuncPtr<void(A0, A1, A2, A3, A4)> callback) {
+    void attach(EventQueue *queue, FuncPtr<void(A0, A1, A2, A3, A4)> func) {
         attach(queue);
-        attach(callback);
+        attach(func);
     }
 
     /** Attach an event to a queue
@@ -83,36 +75,31 @@
      *  @param ms   Delay in milliseconds
      */
     void delay(int ms) {
-        _event.delay = ms;
+        _delay = ms;
     }
 
     /** Set event to repeat periodically after it is posted
      *  @param ms   Period in milliseconds
      */
     void period(int ms) {
-        _event.period = ms;
+        _period = ms;
     }
 
     /** Set tolerance hint on when the event must be called, defaults to 0
      *  @param ms   Tolerance in milliseconds
      */
     void tolerance(int ms) {
-        (void)ms; // currently ignored
+        _tolerance = ms;
     }
 
     /** Post the event onto the bound queue
+     *  @param ms   Max time to wait if memory is not available in milliseconds
      *  @return     True if the event was posted successfully
      */
-    bool trigger(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
-        if (_event.registered) {
-            return false;
-        }
-
-        _bind.attach(_callback, a0, a1, a2, a3, a4);
-        _event.callback = Binder<void(A0, A1, A2, A3, A4), A0, A1, A2, A3, A4>::thunk;
-        _event.data = &_bind;
-        _queue->event_register(&_event, _event.delay);
-        return true;
+    bool trigger(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, int ms=-1) {
+        return _queue->trigger(
+                Binder<void(A0,A1,A2,A3,A4),A0,A1,A2,A3,A4>(_func,a0,a1,a2,a3,a4),
+                _delay, _period, _tolerance, ms);
     }
 
     /** Post the event onto the bound queue
@@ -130,7 +117,7 @@
     /** Test if event has been bound
      */
     operator bool() const {
-        return _callback && _queue;
+        return _func && _queue;
     }
 
     /** Static thunk for passing as C-style function
@@ -141,17 +128,12 @@
                 ->call(a0, a1, a2, a3, a4);
     }
 
-    /** Cancel a pending event
-     */
-    void cancel() {
-        _queue->event_unregister(&_event);
-    }
-
 private:
+    FuncPtr<void(A0,A1,A2,A3,A4)> _func;
     EventQueue *_queue;
-    EventQueue::event _event;
-    FuncPtr<void(A0, A1, A2, A3, A4)> _callback;
-    Binder<void(A0, A1, A2, A3, A4), A0, A1, A2, A3, A4> _bind;
+    int _delay;
+    int _period;
+    int _tolerance;
 };
 
 /** Pendable event class
@@ -161,29 +143,21 @@
 public:
     /** Create an event bound to a queue
      */
-    Event(EventQueue *queue=0, FuncPtr<void(A0, A1, A2, A3)> callback=0) {
-        memset(&_event, 0, sizeof _event);
-        _event.delay = 0;
-        _event.period = -1;
-        attach(queue, callback);
+    Event(EventQueue *queue=0, FuncPtr<void(A0, A1, A2, A3)> func=0) {
+        _delay = 0;
+        _period = -1;
+        attach(queue, func);
     }
 
     /** Create an event bound to a queue
      */
     template <typename T, typename M>
     Event(EventQueue *queue, T *obj, M method) {
-        memset(&_event, 0, sizeof _event);
-        _event.delay = 0;
-        _event.period = -1;
+        _delay = 0;
+        _period = -1;
         attach(queue, obj, method);
     }
 
-    /** Safe lifetime management
-     */
-    ~Event() {
-        cancel();
-    }
-
     /** Attach an event to a queue
      */
     void attach(EventQueue *queue) {
@@ -192,8 +166,8 @@
 
     /** Attach a callback to an event
      */
-    void attach(FuncPtr<void(A0, A1, A2, A3)> callback) {
-        _callback.attach(callback);
+    void attach(FuncPtr<void(A0, A1, A2, A3)> func) {
+        _func.attach(func);
     }
 
     /** Attach a callback to an event
@@ -203,11 +177,11 @@
         attach(FuncPtr<void(A0, A1, A2, A3)>(obj, method));
     }
 
-    /** Attach a callback to an event
+    /** Attach a func to an event
      */
-    void attach(EventQueue *queue, FuncPtr<void(A0, A1, A2, A3)> callback) {
+    void attach(EventQueue *queue, FuncPtr<void(A0, A1, A2, A3)> func) {
         attach(queue);
-        attach(callback);
+        attach(func);
     }
 
     /** Attach an event to a queue
@@ -222,35 +196,31 @@
      *  @param ms   Delay in milliseconds
      */
     void delay(int ms) {
-        _event.delay = ms;
+        _delay = ms;
     }
 
     /** Set event to repeat periodically after it is posted
      *  @param ms   Period in milliseconds
      */
     void period(int ms) {
-        _event.period = ms;
+        _period = ms;
     }
 
     /** Set tolerance hint on when the event must be called, defaults to 0
      *  @param ms   Tolerance in milliseconds
      */
     void tolerance(int ms) {
-        (void)ms; // currently ignored
+        _tolerance = ms;
     }
 
     /** Post the event onto the bound queue
+     *  @param ms   Max time to wait if memory is not available in milliseconds
+     *  @return     True if the event was posted successfully
      */
-    bool trigger(A0 a0, A1 a1, A2 a2, A3 a3) {
-        if (_event.registered) {
-            return false;
-        }
-
-        _bind.attach(_callback, a0, a1, a2, a3);
-        _event.callback = Binder<void(A0, A1, A2, A3), A0, A1, A2, A3>::thunk;
-        _event.data = &_bind;
-        _queue->event_register(&_event, _event.delay);
-        return true;
+    bool trigger(A0 a0, A1 a1, A2 a2, A3 a3, int ms=-1) {
+        return _queue->trigger(
+                Binder<void(A0,A1,A2,A3),A0,A1,A2,A3>(_func,a0,a1,a2,a3),
+                _delay, _period, _tolerance, ms);
     }
 
     /** Post the event onto the bound queue
@@ -268,7 +238,7 @@
     /** Test if event has been bound
      */
     operator bool() const {
-        return _callback && _queue;
+        return _func && _queue;
     }
 
     /** Static thunk for passing as C-style function
@@ -279,17 +249,12 @@
                 ->call(a0, a1, a2, a3);
     }
 
-    /** Cancel a pending event
-     */
-    void cancel() {
-        _queue->event_unregister(&_event);
-    }
-
 private:
+    FuncPtr<void(A0,A1,A2,A3)> _func;
     EventQueue *_queue;
-    EventQueue::event _event;
-    FuncPtr<void(A0, A1, A2, A3)> _callback;
-    Binder<void(A0, A1, A2, A3), A0, A1, A2, A3> _bind;
+    int _delay;
+    int _period;
+    int _tolerance;
 };
 
 /** Pendable event class
@@ -299,29 +264,21 @@
 public:
     /** Create an event bound to a queue
      */
-    Event(EventQueue *queue=0, FuncPtr<void(A0, A1, A2)> callback=0) {
-        memset(&_event, 0, sizeof _event);
-        _event.delay = 0;
-        _event.period = -1;
-        attach(queue, callback);
+    Event(EventQueue *queue=0, FuncPtr<void(A0, A1, A2)> func=0) {
+        _delay = 0;
+        _period = -1;
+        attach(queue, func);
     }
 
     /** Create an event bound to a queue
      */
     template <typename T, typename M>
     Event(EventQueue *queue, T *obj, M method) {
-        memset(&_event, 0, sizeof _event);
-        _event.delay = 0;
-        _event.period = -1;
+        _delay = 0;
+        _period = -1;
         attach(queue, obj, method);
     }
 
-    /** Safe lifetime management
-     */
-    ~Event() {
-        cancel();
-    }
-
     /** Attach an event to a queue
      */
     void attach(EventQueue *queue) {
@@ -330,8 +287,8 @@
 
     /** Attach a callback to an event
      */
-    void attach(FuncPtr<void(A0, A1, A2)> callback) {
-        _callback.attach(callback);
+    void attach(FuncPtr<void(A0, A1, A2)> func) {
+        _func.attach(func);
     }
 
     /** Attach a callback to an event
@@ -341,11 +298,11 @@
         attach(FuncPtr<void(A0, A1, A2)>(obj, method));
     }
 
-    /** Attach a callback to an event
+    /** Attach a func to an event
      */
-    void attach(EventQueue *queue, FuncPtr<void(A0, A1, A2)> callback) {
+    void attach(EventQueue *queue, FuncPtr<void(A0, A1, A2)> func) {
         attach(queue);
-        attach(callback);
+        attach(func);
     }
 
     /** Attach an event to a queue
@@ -360,35 +317,31 @@
      *  @param ms   Delay in milliseconds
      */
     void delay(int ms) {
-        _event.delay = ms;
+        _delay = ms;
     }
 
     /** Set event to repeat periodically after it is posted
      *  @param ms   Period in milliseconds
      */
     void period(int ms) {
-        _event.period = ms;
+        _period = ms;
     }
 
     /** Set tolerance hint on when the event must be called, defaults to 0
      *  @param ms   Tolerance in milliseconds
      */
     void tolerance(int ms) {
-        (void)ms; // currently ignored
+        _tolerance = ms;
     }
 
     /** Post the event onto the bound queue
+     *  @param ms   Max time to wait if memory is not available in milliseconds
+     *  @return     True if the event was posted successfully
      */
-    bool trigger(A0 a0, A1 a1, A2 a2) {
-        if (_event.registered) {
-            return false;
-        }
-
-        _bind.attach(_callback, a0, a1, a2);
-        _event.callback = Binder<void(A0, A1, A2), A0, A1, A2>::thunk;
-        _event.data = &_bind;
-        _queue->event_register(&_event, _event.delay);
-        return true;
+    bool trigger(A0 a0, A1 a1, A2 a2, int ms=-1) {
+        return _queue->trigger(
+                Binder<void(A0,A1,A2),A0,A1,A2>(_func,a0,a1,a2),
+                _delay, _period, _tolerance, ms);
     }
 
     /** Post the event onto the bound queue
@@ -406,7 +359,7 @@
     /** Test if event has been bound
      */
     operator bool() const {
-        return _callback && _queue;
+        return _func && _queue;
     }
 
     /** Static thunk for passing as C-style function
@@ -417,17 +370,12 @@
                 ->call(a0, a1, a2);
     }
 
-    /** Cancel a pending event
-     */
-    void cancel() {
-        _queue->event_unregister(&_event);
-    }
-
 private:
+    FuncPtr<void(A0,A1,A2)> _func;
     EventQueue *_queue;
-    EventQueue::event _event;
-    FuncPtr<void(A0, A1, A2)> _callback;
-    Binder<void(A0, A1, A2), A0, A1, A2> _bind;
+    int _delay;
+    int _period;
+    int _tolerance;
 };
 
 /** Pendable event class
@@ -437,29 +385,21 @@
 public:
     /** Create an event bound to a queue
      */
-    Event(EventQueue *queue=0, FuncPtr<void(A0, A1)> callback=0) {
-        memset(&_event, 0, sizeof _event);
-        _event.delay = 0;
-        _event.period = -1;
-        attach(queue, callback);
+    Event(EventQueue *queue=0, FuncPtr<void(A0, A1)> func=0) {
+        _delay = 0;
+        _period = -1;
+        attach(queue, func);
     }
 
     /** Create an event bound to a queue
      */
     template <typename T, typename M>
     Event(EventQueue *queue, T *obj, M method) {
-        memset(&_event, 0, sizeof _event);
-        _event.delay = 0;
-        _event.period = -1;
+        _delay = 0;
+        _period = -1;
         attach(queue, obj, method);
     }
 
-    /** Safe lifetime management
-     */
-    ~Event() {
-        cancel();
-    }
-
     /** Attach an event to a queue
      */
     void attach(EventQueue *queue) {
@@ -468,8 +408,8 @@
 
     /** Attach a callback to an event
      */
-    void attach(FuncPtr<void(A0, A1)> callback) {
-        _callback.attach(callback);
+    void attach(FuncPtr<void(A0, A1)> func) {
+        _func.attach(func);
     }
 
     /** Attach a callback to an event
@@ -479,11 +419,11 @@
         attach(FuncPtr<void(A0, A1)>(obj, method));
     }
 
-    /** Attach a callback to an event
+    /** Attach a func to an event
      */
-    void attach(EventQueue *queue, FuncPtr<void(A0, A1)> callback) {
+    void attach(EventQueue *queue, FuncPtr<void(A0, A1)> func) {
         attach(queue);
-        attach(callback);
+        attach(func);
     }
 
     /** Attach an event to a queue
@@ -498,35 +438,31 @@
      *  @param ms   Delay in milliseconds
      */
     void delay(int ms) {
-        _event.delay = ms;
+        _delay = ms;
     }
 
     /** Set event to repeat periodically after it is posted
      *  @param ms   Period in milliseconds
      */
     void period(int ms) {
-        _event.period = ms;
+        _period = ms;
     }
 
     /** Set tolerance hint on when the event must be called, defaults to 0
      *  @param ms   Tolerance in milliseconds
      */
     void tolerance(int ms) {
-        (void)ms; // currently ignored
+        _tolerance = ms;
     }
 
     /** Post the event onto the bound queue
+     *  @param ms   Max time to wait if memory is not available in milliseconds
+     *  @return     True if the event was posted successfully
      */
-    bool trigger(A0 a0, A1 a1) {
-        if (_event.registered) {
-            return false;
-        }
-
-        _bind.attach(_callback, a0, a1);
-        _event.callback = Binder<void(A0, A1), A0, A1>::thunk;
-        _event.data = &_bind;
-        _queue->event_register(&_event, _event.delay);
-        return true;
+    bool trigger(A0 a0, A1 a1, int ms=-1) {
+        return _queue->trigger(
+                Binder<void(A0,A1),A0,A1>(_func,a0,a1),
+                _delay, _period, _tolerance, ms);
     }
 
     /** Post the event onto the bound queue
@@ -544,7 +480,7 @@
     /** Test if event has been bound
      */
     operator bool() const {
-        return _callback && _queue;
+        return _func && _queue;
     }
 
     /** Static thunk for passing as C-style function
@@ -555,17 +491,12 @@
                 ->call(a0, a1);
     }
 
-    /** Cancel a pending event
-     */
-    void cancel() {
-        _queue->event_unregister(&_event);
-    }
-
 private:
+    FuncPtr<void(A0,A1)> _func;
     EventQueue *_queue;
-    EventQueue::event _event;
-    FuncPtr<void(A0, A1)> _callback;
-    Binder<void(A0, A1), A0, A1> _bind;
+    int _delay;
+    int _period;
+    int _tolerance;
 };
 
 /** Pendable event class
@@ -575,29 +506,21 @@
 public:
     /** Create an event bound to a queue
      */
-    Event(EventQueue *queue=0, FuncPtr<void(A0)> callback=0) {
-        memset(&_event, 0, sizeof _event);
-        _event.delay = 0;
-        _event.period = -1;
-        attach(queue, callback);
+    Event(EventQueue *queue=0, FuncPtr<void(A0)> func=0) {
+        _delay = 0;
+        _period = -1;
+        attach(queue, func);
     }
 
     /** Create an event bound to a queue
      */
     template <typename T, typename M>
     Event(EventQueue *queue, T *obj, M method) {
-        memset(&_event, 0, sizeof _event);
-        _event.delay = 0;
-        _event.period = -1;
+        _delay = 0;
+        _period = -1;
         attach(queue, obj, method);
     }
 
-    /** Safe lifetime management
-     */
-    ~Event() {
-        cancel();
-    }
-
     /** Attach an event to a queue
      */
     void attach(EventQueue *queue) {
@@ -606,8 +529,8 @@
 
     /** Attach a callback to an event
      */
-    void attach(FuncPtr<void(A0)> callback) {
-        _callback.attach(callback);
+    void attach(FuncPtr<void(A0)> func) {
+        _func.attach(func);
     }
 
     /** Attach a callback to an event
@@ -617,11 +540,11 @@
         attach(FuncPtr<void(A0)>(obj, method));
     }
 
-    /** Attach a callback to an event
+    /** Attach a func to an event
      */
-    void attach(EventQueue *queue, FuncPtr<void(A0)> callback) {
+    void attach(EventQueue *queue, FuncPtr<void(A0)> func) {
         attach(queue);
-        attach(callback);
+        attach(func);
     }
 
     /** Attach an event to a queue
@@ -636,35 +559,31 @@
      *  @param ms   Delay in milliseconds
      */
     void delay(int ms) {
-        _event.delay = ms;
+        _delay = ms;
     }
 
     /** Set event to repeat periodically after it is posted
      *  @param ms   Period in milliseconds
      */
     void period(int ms) {
-        _event.period = ms;
+        _period = ms;
     }
 
     /** Set tolerance hint on when the event must be called, defaults to 0
      *  @param ms   Tolerance in milliseconds
      */
     void tolerance(int ms) {
-        (void)ms; // currently ignored
+        _tolerance = ms;
     }
 
     /** Post the event onto the bound queue
+     *  @param ms   Max time to wait if memory is not available in milliseconds
+     *  @return     True if the event was posted successfully
      */
-    bool trigger(A0 a0) {
-        if (_event.registered) {
-            return false;
-        }
-
-        _bind.attach(_callback, a0);
-        _event.callback = Binder<void(A0), A0>::thunk;
-        _event.data = &_bind;
-        _queue->event_register(&_event, _event.delay);
-        return true;
+    bool trigger(A0 a0, int ms=-1) {
+        return _queue->trigger(
+                Binder<void(A0),A0>(_func,a0),
+                _delay, _period, _tolerance, ms);
     }
 
     /** Post the event onto the bound queue
@@ -682,7 +601,7 @@
     /** Test if event has been bound
      */
     operator bool() const {
-        return _callback && _queue;
+        return _func && _queue;
     }
 
     /** Static thunk for passing as C-style function
@@ -693,17 +612,12 @@
                 ->call(a0);
     }
 
-    /** Cancel a pending event
-     */
-    void cancel() {
-        _queue->event_unregister(&_event);
-    }
-
 private:
+    FuncPtr<void(A0)> _func;
     EventQueue *_queue;
-    EventQueue::event _event;
-    FuncPtr<void(A0)> _callback;
-    Binder<void(A0), A0> _bind;
+    int _delay;
+    int _period;
+    int _tolerance;
 };
 
 /** Pendable event class
@@ -711,39 +625,23 @@
 template <>
 class Event<void()> {
 public:
-    /** Create an unbound event
-     */
-    Event() {
-        memset(&_event, 0, sizeof _event);
-        _event.delay = 0;
-        _event.period = -1;
-    }
-
     /** Create an event bound to a queue
      */
-    Event(EventQueue *queue=0, FuncPtr<void()> callback=0) {
-        memset(&_event, 0, sizeof _event);
-        _event.delay = 0;
-        _event.period = -1;
-        attach(queue, callback);
+    Event(EventQueue *queue=0, FuncPtr<void()> func=0) {
+        _delay = 0;
+        _period = -1;
+        attach(queue, func);
     }
 
     /** Create an event bound to a queue
      */
     template <typename T, typename M>
     Event(EventQueue *queue, T *obj, M method) {
-        memset(&_event, 0, sizeof _event);
-        _event.delay = 0;
-        _event.period = -1;
+        _delay = 0;
+        _period = -1;
         attach(queue, obj, method);
     }
 
-    /** Safe lifetime management
-     */
-    ~Event() {
-        cancel();
-    }
-
     /** Attach an event to a queue
      */
     void attach(EventQueue *queue) {
@@ -752,8 +650,8 @@
 
     /** Attach a callback to an event
      */
-    void attach(FuncPtr<void()> callback) {
-        _callback.attach(callback);
+    void attach(FuncPtr<void()> func) {
+        _func.attach(func);
     }
 
     /** Attach a callback to an event
@@ -763,11 +661,11 @@
         attach(FuncPtr<void()>(obj, method));
     }
 
-    /** Attach a callback to an event
+    /** Attach a func to an event
      */
-    void attach(EventQueue *queue, FuncPtr<void()> callback) {
+    void attach(EventQueue *queue, FuncPtr<void()> func) {
         attach(queue);
-        attach(callback);
+        attach(func);
     }
 
     /** Attach an event to a queue
@@ -782,34 +680,29 @@
      *  @param ms   Delay in milliseconds
      */
     void delay(int ms) {
-        _event.delay = ms;
+        _delay = ms;
     }
 
     /** Set event to repeat periodically after it is posted
      *  @param ms   Period in milliseconds
      */
     void period(int ms) {
-        _event.period = ms;
+        _period = ms;
     }
 
     /** Set tolerance hint on when the event must be called, defaults to 0
      *  @param ms   Tolerance in milliseconds
      */
     void tolerance(int ms) {
-        (void)ms; // currently ignored
+        _tolerance = ms;
     }
 
     /** Post the event onto the bound queue
+     *  @param ms   Max time to wait if memory is not available in milliseconds
+     *  @return     True if the event was posted successfully
      */
-    bool trigger() {
-        if (_event.registered) {
-            return false;
-        }
-
-        _event.callback = FuncPtr<void()>::thunk;
-        _event.data = &_callback;
-        _queue->event_register(&_event, _event.delay);
-        return true;
+    bool trigger(int ms=-1) {
+        return _queue->trigger(_func, _delay, _period, _tolerance, ms);
     }
 
     /** Post the event onto the bound queue
@@ -827,7 +720,7 @@
     /** Test if event has been bound
      */
     operator bool() const {
-        return _callback && _queue;
+        return _func && _queue;
     }
 
     /** Static thunk for passing as C-style function
@@ -838,16 +731,12 @@
                 ->call();
     }
 
-    /** Cancel a pending event
-     */
-    void cancel() {
-        _queue->event_unregister(&_event);
-    }
-
 private:
+    FuncPtr<void()> _func;
     EventQueue *_queue;
-    EventQueue::event _event;
-    FuncPtr<void()> _callback;
+    int _delay;
+    int _period;
+    int _tolerance;
 };