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.
Event.h
- Committer:
- Christopher Haster
- Date:
- 2016-04-20
- Revision:
- 0:b1b901ae3696
- Child:
- 2:11cda6bead99
File content as of revision 0:b1b901ae3696:
/* 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