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.
EventQueue.h
- Committer:
- Christopher Haster
- Date:
- 2016-04-18
- Revision:
- 20:2f9d9c53a5af
- Parent:
- 19:86ffaa34870b
File content as of revision 20:2f9d9c53a5af:
/* EventQueue * * Flexible queue for managing events */ #ifndef EVENT_QUEUE_H #define EVENT_QUEUE_H #include "Timer.h" #include "Ticker.h" #include "FuncPtr.h" #include "Binder.h" /** Flexible queue for managing events */ class EventQueue { public: /** Create an event queue * @param event_count Number of events to allow enqueueing at once * (default: 32) * @param event_context Max size of arguments passed with an event * (default: 0) * @param event_pointer Pointer to memory area to be used for events * (default: NULL) */ EventQueue(unsigned event_count=32, unsigned event_context=0, unsigned char *event_pointer=NULL); /** Clean up event queue */ ~EventQueue(); /** Dispatch pending events * @param ms Time to wait for events in milliseconds, * 0 indicates to return immediately if no events are pending */ void dispatch(int ms=-1); /** Get current tick of the event queue * @return Number of milliseconds since the queue was instantiated, * this count intentionally overflows to 0 after 2^32-1 */ unsigned get_tick(); /** Determine if tick has been passed * @param Tick to check * @param True if tick has been passed */ bool past_tick(unsigned tick); private: struct event { struct event *volatile next; unsigned target; int period; void (*dispatch)(void *p); // data follows }; struct event *event_alloc(unsigned size, int ms=-1); void event_dealloc(struct event *); void event_trigger(struct event *e, int delay); template <typename F> 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; } e->period = period; (void)tolerance; // unused e->dispatch = &F::thunk; *reinterpret_cast<F*>(e+1) = func; event_trigger(e, delay); return true; } void tick(); unsigned _event_context; void *_mem; struct event *volatile _free; struct event *volatile _queue; unsigned _tick; mbed::Ticker _ticker; mbed::Timer _timer; 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); } 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); } 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); } 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); } 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); } 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); } 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); } 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); } 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); } template <typename T, typename A0> bool trigger(T *obj, void (*func)(T*,A0), A0 a0) { return trigger(FuncPtr<void(A0)>(obj,func),a0); } 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); } template <typename T> bool trigger(T *obj, void (*func)(T*)) { return trigger(FuncPtr<void()>(obj,func)); } template <typename T> bool trigger(T *obj, void (T::*func)()) { return trigger(FuncPtr<void()>(obj,func)); } /** Post an event after a specified time * @param ms Delay 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) { return event_trigger(Binder<void(A0,A1,A2,A3,A4),A0,A1,A2,A3,A4>(func,a0,a1,a2,a3,a4), ms, -1, 0); } 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) { return trigger_in(FuncPtr<void(A0,A1,A2,A3,A4)>(obj,func),a0,a1,a2,a3,a4,ms); } 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) { 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 * @param ms Delay 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) { return event_trigger(Binder<void(A0,A1,A2,A3),A0,A1,A2,A3>(func,a0,a1,a2,a3), ms, -1, 0); } 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) { return trigger_in(FuncPtr<void(A0,A1,A2,A3)>(obj,func),a0,a1,a2,a3,ms); } 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) { return trigger_in(FuncPtr<void(A0,A1,A2,A3)>(obj,func),a0,a1,a2,a3,ms); } /** Post an event after a specified time * @param ms Delay in milliseconds */ template <typename F, typename A0, typename A1, typename A2> bool trigger_in(F func, A0 a0, A1 a1, A2 a2, int ms) { return event_trigger(Binder<void(A0,A1,A2),A0,A1,A2>(func,a0,a1,a2), ms, -1, 0); } 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) { return trigger_in(FuncPtr<void(A0,A1,A2)>(obj,func),a0,a1,a2,ms); } 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) { return trigger_in(FuncPtr<void(A0,A1,A2)>(obj,func),a0,a1,a2,ms); } /** Post an event after a specified time * @param ms Delay in milliseconds */ template <typename F, typename A0, typename A1> bool trigger_in(F func, A0 a0, A1 a1, int ms) { return event_trigger(Binder<void(A0,A1),A0,A1>(func,a0,a1), ms, -1, 0); } template <typename T, typename A0, typename A1> bool trigger_in(T *obj, void (*func)(T*,A0,A1), A0 a0, A1 a1, int ms) { return trigger_in(FuncPtr<void(A0,A1)>(obj,func),a0,a1,ms); } template <typename T, typename A0, typename A1> bool trigger_in(T *obj, void (T::*func)(A0,A1), A0 a0, A1 a1, int ms) { return trigger_in(FuncPtr<void(A0,A1)>(obj,func),a0,a1,ms); } /** Post an event after a specified time * @param ms Delay in milliseconds */ template <typename F, typename A0> bool trigger_in(F func, A0 a0, int ms) { return event_trigger(Binder<void(A0),A0>(func,a0), ms, -1, 0); } template <typename T, typename A0> bool trigger_in(T *obj, void (*func)(T*,A0), A0 a0, int ms) { return trigger_in(FuncPtr<void(A0)>(obj,func),a0,ms); } template <typename T, typename A0> bool trigger_in(T *obj, void (T::*func)(A0), A0 a0, int ms) { return trigger_in(FuncPtr<void(A0)>(obj,func),a0,ms); } /** Post an event after a specified time * @param ms Delay in milliseconds */ template <typename F> bool trigger_in(F func, int ms) { return event_trigger(Binder<void()>(func), ms, -1, 0); } template <typename T> bool trigger_in(T *obj, void (*func)(T*), int ms) { return trigger_in(FuncPtr<void()>(obj,func),ms); } template <typename T> bool trigger_in(T *obj, void (T::*func)(), int ms) { return trigger_in(FuncPtr<void()>(obj,func),ms); } /** Post an event periodically * @param ms Delay 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) { return event_trigger(Binder<void(A0,A1,A2,A3,A4),A0,A1,A2,A3,A4>(func,a0,a1,a2,a3,a4), 0, ms, 0); } 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) { return trigger_every(FuncPtr<void(A0,A1,A2,A3,A4)>(obj,func),a0,a1,a2,a3,a4,ms); } 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) { return trigger_every(FuncPtr<void(A0,A1,A2,A3,A4)>(obj,func),a0,a1,a2,a3,a4,ms); } /** Post an event periodically * @param ms Delay 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) { return event_trigger(Binder<void(A0,A1,A2,A3),A0,A1,A2,A3>(func,a0,a1,a2,a3), 0, ms, 0); } 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) { return trigger_every(FuncPtr<void(A0,A1,A2,A3)>(obj,func),a0,a1,a2,a3,ms); } 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) { return trigger_every(FuncPtr<void(A0,A1,A2,A3)>(obj,func),a0,a1,a2,a3,ms); } /** Post an event periodically * @param ms Delay in milliseconds */ template <typename F, typename A0, typename A1, typename A2> bool trigger_every(F func, A0 a0, A1 a1, A2 a2, int ms) { return event_trigger(Binder<void(A0,A1,A2),A0,A1,A2>(func,a0,a1,a2), 0, ms, 0); } 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) { return trigger_every(FuncPtr<void(A0,A1,A2)>(obj,func),a0,a1,a2,ms); } 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) { return trigger_every(FuncPtr<void(A0,A1,A2)>(obj,func),a0,a1,a2,ms); } /** Post an event periodically * @param ms Delay in milliseconds */ template <typename F, typename A0, typename A1> bool trigger_every(F func, A0 a0, A1 a1, int ms) { return event_trigger(Binder<void(A0,A1),A0,A1>(func,a0,a1), 0, ms, 0); } template <typename T, typename A0, typename A1> bool trigger_every(T *obj, void (*func)(T*,A0,A1), A0 a0, A1 a1, int ms) { return trigger_every(FuncPtr<void(A0,A1)>(obj,func),a0,a1,ms); } template <typename T, typename A0, typename A1> bool trigger_every(T *obj, void (T::*func)(A0,A1), A0 a0, A1 a1, int ms) { return trigger_every(FuncPtr<void(A0,A1)>(obj,func),a0,a1,ms); } /** Post an event periodically * @param ms Delay in milliseconds */ template <typename F, typename A0> bool trigger_every(F func, A0 a0, int ms) { return event_trigger(Binder<void(A0),A0>(func,a0), 0, ms, 0); } template <typename T, typename A0> bool trigger_every(T *obj, void (*func)(T*,A0), A0 a0, int ms) { return trigger_every(FuncPtr<void(A0)>(obj,func),a0,ms); } template <typename T, typename A0> bool trigger_every(T *obj, void (T::*func)(A0), A0 a0, int ms) { return trigger_every(FuncPtr<void(A0)>(obj,func),a0,ms); } /** Post an event periodically * @param ms Delay in milliseconds */ template <typename F> bool trigger_every(F func, int ms) { return event_trigger(Binder<void()>(func), 0, ms, 0); } template <typename T> bool trigger_every(T *obj, void (*func)(T*), int ms) { return trigger_every(FuncPtr<void()>(obj,func),ms); } template <typename T> bool trigger_every(T *obj, void (T::*func)(), int ms) { return trigger_every(FuncPtr<void()>(obj,func),ms); } }; #endif