Note! This project has moved to github.com/armmbed/mbed-events
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.
Diff: Event.h
- Revision:
- 0:b1b901ae3696
- Child:
- 2:11cda6bead99
diff -r 000000000000 -r b1b901ae3696 Event.h --- /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