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:
0:b1b901ae3696
Child:
2:11cda6bead99
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Event.h	Wed Apr 20 11:43:51 2016 -0500
@@ -0,0 +1,367 @@
+/*  Event
+ *
+ *  Pendable event
+ */
+#ifndef EVENT_H
+#define EVENT_H
+
+#include "EventQueue.h"
+#include "FuncPtr.h"
+#include "Binder.h"
+
+
+/** Pendable event class
+ */
+template <typename F>
+class Event;
+
+/** Pendable event class
+ */
+template <typename A0, typename A1, typename A2, typename A3>
+class Event<void(A0, A1, A2, A3)> {
+public:
+    /** Create an unbound event
+     */
+    Event() {}
+
+    /** Create an event bound to a queue
+     */
+    Event(EventQueue *queue, FuncPtr<void(A0, A1, A2, A3)> callback) {
+        attach(queue, callback);
+    }
+
+    /** Safe lifetime management
+     */
+    ~Event() {
+        cancel();
+    }
+
+    /** Attach an event to a queue
+     */
+    void attach(EventQueue *queue, FuncPtr<void(A0, A1, A2, A3)> callback) {
+        _queue = queue;
+        _callback.attach(callback);
+    }
+
+    /** Dispatch the event onto the bound queue
+     */
+    void call(A0 a0, A1 a1, A2 a2, A3 a3) {
+        _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);
+    }
+
+    /** Dispatch the event onto the bound queue
+     */
+    void operator()(A0 a0, A1 a1, A2 a2, A3 a3) {
+        return call(a0, a1, a2, a3);
+    }
+
+    /** Test if event has been bound
+     */
+    operator bool() const {
+        return _callback && _queue;
+    }
+
+    /** Static thunk for passing as C-style function
+     *  @param data Event to dispatch passed as void pointer
+     */
+    static void thunk(void *data, A0 a0, A1 a1, A2 a2, A3 a3) {
+        return static_cast<Event<void(A0, A1, A2, A3)>*>(data)
+                ->call(a0, a1, a2, a3);
+    }
+
+    /** Cancel a pending event
+     */
+    void cancel() {
+        _queue->event_unregister(&_event);
+    }
+
+private:
+    EventQueue *_queue;
+    EventQueue::event _event;
+    FuncPtr<void(A0, A1, A2, A3)> _callback;
+    Binder<void(A0, A1, A2, A3), A0, A1, A2, A3> _bind;
+};
+
+/** Pendable event class
+ */
+template <typename A0, typename A1, typename A2>
+class Event<void(A0, A1, A2)> {
+public:
+    /** Create an unbound event
+     */
+    Event() {}
+
+    /** Create an event bound to a queue
+     */
+    Event(EventQueue *queue, FuncPtr<void(A0, A1, A2)> callback) {
+        attach(queue, callback);
+    }
+
+    /** Safe lifetime management
+     */
+    ~Event() {
+        cancel();
+    }
+
+    /** Attach an event to a queue
+     */
+    void attach(EventQueue *queue, FuncPtr<void(A0, A1, A2)> callback) {
+        _queue = queue;
+        _callback.attach(callback);
+    }
+
+    /** Dispatch the event onto the bound queue
+     */
+    void call(A0 a0, A1 a1, A2 a2) {
+        _bind.attach(_callback, a0, a1, a2);
+        _event.callback = Binder<void(A0, A1, A2), A0, A1, A2>::thunk;
+        _event.data = &_bind;
+        _queue->event_register(&_event);
+    }
+
+    /** Dispatch the event onto the bound queue
+     */
+    void operator()(A0 a0, A1 a1, A2 a2) {
+        return call(a0, a1, a2);
+    }
+
+    /** Test if event has been bound
+     */
+    operator bool() const {
+        return _callback && _queue;
+    }
+
+    /** Static thunk for passing as C-style function
+     *  @param data Event to dispatch passed as void pointer
+     */
+    static void thunk(void *data, A0 a0, A1 a1, A2 a2) {
+        return static_cast<Event<void(A0, A1, A2)>*>(data)
+                ->call(a0, a1, a2);
+    }
+
+    /** Cancel a pending event
+     */
+    void cancel() {
+        _queue->event_unregister(&_event);
+    }
+
+private:
+    EventQueue *_queue;
+    EventQueue::event _event;
+    FuncPtr<void(A0, A1, A2)> _callback;
+    Binder<void(A0, A1, A2), A0, A1, A2> _bind;
+};
+
+/** Pendable event class
+ */
+template <typename A0, typename A1>
+class Event<void(A0, A1)> {
+public:
+    /** Create an unbound event
+     */
+    Event() {}
+
+    /** Create an event bound to a queue
+     */
+    Event(EventQueue *queue, FuncPtr<void(A0, A1)> callback) {
+        attach(queue, callback);
+    }
+
+    /** Safe lifetime management
+     */
+    ~Event() {
+        cancel();
+    }
+
+    /** Attach an event to a queue
+     */
+    void attach(EventQueue *queue, FuncPtr<void(A0, A1)> callback) {
+        _queue = queue;
+        _callback.attach(callback);
+    }
+
+    /** Dispatch the event onto the bound queue
+     */
+    void call(A0 a0, A1 a1) {
+        _bind.attach(_callback, a0, a1);
+        _event.callback = Binder<void(A0, A1), A0, A1>::thunk;
+        _event.data = &_bind;
+        _queue->event_register(&_event);
+    }
+
+    /** Dispatch the event onto the bound queue
+     */
+    void operator()(A0 a0, A1 a1) {
+        return call(a0, a1);
+    }
+
+    /** Test if event has been bound
+     */
+    operator bool() const {
+        return _callback && _queue;
+    }
+
+    /** Static thunk for passing as C-style function
+     *  @param data Event to dispatch passed as void pointer
+     */
+    static void thunk(void *data, A0 a0, A1 a1) {
+        return static_cast<Event<void(A0, A1)>*>(data)
+                ->call(a0, a1);
+    }
+
+    /** Cancel a pending event
+     */
+    void cancel() {
+        _queue->event_unregister(&_event);
+    }
+
+private:
+    EventQueue *_queue;
+    EventQueue::event _event;
+    FuncPtr<void(A0, A1)> _callback;
+    Binder<void(A0, A1), A0, A1> _bind;
+};
+
+/** Pendable event class
+ */
+template <typename A0>
+class Event<void(A0)> {
+public:
+    /** Create an unbound event
+     */
+    Event() {}
+
+    /** Create an event bound to a queue
+     */
+    Event(EventQueue *queue, FuncPtr<void(A0)> callback) {
+        attach(queue, callback);
+    }
+
+    /** Safe lifetime management
+     */
+    ~Event() {
+        cancel();
+    }
+
+    /** Attach an event to a queue
+     */
+    void attach(EventQueue *queue, FuncPtr<void(A0)> callback) {
+        _queue = queue;
+        _callback.attach(callback);
+    }
+
+    /** Dispatch the event onto the bound queue
+     */
+    void call(A0 a0) {
+        _bind.attach(_callback, a0);
+        _event.callback = Binder<void(A0), A0>::thunk;
+        _event.data = &_bind;
+        _queue->event_register(&_event);
+    }
+
+    /** Dispatch the event onto the bound queue
+     */
+    void operator()(A0 a0) {
+        return call(a0);
+    }
+
+    /** Test if event has been bound
+     */
+    operator bool() const {
+        return _callback && _queue;
+    }
+
+    /** Static thunk for passing as C-style function
+     *  @param data Event to dispatch passed as void pointer
+     */
+    static void thunk(void *data, A0 a0) {
+        return static_cast<Event<void(A0)>*>(data)
+                ->call(a0);
+    }
+
+    /** Cancel a pending event
+     */
+    void cancel() {
+        _queue->event_unregister(&_event);
+    }
+
+private:
+    EventQueue *_queue;
+    EventQueue::event _event;
+    FuncPtr<void(A0)> _callback;
+    Binder<void(A0), A0> _bind;
+};
+
+/** Pendable event class
+ */
+template <>
+class Event<void()> {
+public:
+    /** Create an unbound event
+     */
+    Event() {}
+
+    /** Create an event bound to a queue
+     */
+    Event(EventQueue *queue, FuncPtr<void()> callback) {
+        attach(queue, callback);
+    }
+
+    /** Safe lifetime management
+     */
+    ~Event() {
+        cancel();
+    }
+
+    /** Attach an event to a queue
+     */
+    void attach(EventQueue *queue, FuncPtr<void()> callback) {
+        _queue = queue;
+        _callback.attach(callback);
+    }
+
+    /** Dispatch the event onto the bound queue
+     */
+    void call() {
+        _event.callback = FuncPtr<void()>::thunk;
+        _event.data = &_callback;
+        _queue->event_register(&_event);
+    }
+
+    /** Dispatch the event onto the bound queue
+     */
+    void operator()() {
+        return call();
+    }
+
+    /** Test if event has been bound
+     */
+    operator bool() const {
+        return _callback && _queue;
+    }
+
+    /** Static thunk for passing as C-style function
+     *  @param data Event to dispatch passed as void pointer
+     */
+    static void thunk(void *data) {
+        return static_cast<Event<void()>*>(data)
+                ->call();
+    }
+
+    /** Cancel a pending event
+     */
+    void cancel() {
+        _queue->event_unregister(&_event);
+    }
+
+private:
+    EventQueue *_queue;
+    EventQueue::event _event;
+    FuncPtr<void()> _callback;
+};
+
+
+#endif