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: EventQueue.cpp
- Revision:
- 15:92d7c0b8a0f5
- Parent:
- 14:5abf2ccf2dbf
- Child:
- 16:ff5d48fcce1b
--- a/EventQueue.cpp Tue May 10 07:51:44 2016 -0500 +++ b/EventQueue.cpp Tue May 10 09:23:27 2016 -0500 @@ -7,7 +7,27 @@ #endif +// Platform specific definitions +static inline unsigned irq_disable() { + unsigned primask = __get_PRIMASK(); + __disable_irq(); + return primask; +} +static inline void irq_enable(unsigned primask) { + __set_PRIMASK(primask); +} + +static inline void irq_wfi() { +#ifndef EVENTS_NO_RTOS + Thread::yield(); +#else + __WFI(); +#endif +} + + +// Event queue definitions EventQueue::EventQueue(unsigned event_count, unsigned event_context) { _event_context = sizeof(FuncPtr<void()>) + event_context; unsigned event_size = sizeof(struct event) + _event_context; @@ -45,12 +65,18 @@ } +void EventQueue::exit(volatile bool *exit) { + *exit = true; +} + void EventQueue::dispatch(int ms) { Timeout timeout; - struct event exit; + volatile bool exit = false; if (ms >= 0) { - trigger(&exit, ms); + Event<void(volatile bool*)> e(this, this, &EventQueue::exit); + e.delay(ms); + e.trigger(&exit); } while (true) { @@ -64,10 +90,6 @@ struct event *volatile e = _queue; _queue = _queue->next; - if (e == &exit) { - return; - } - e->dispatch(reinterpret_cast<void *>(e + 1)); if (e->period >= 0) { @@ -77,20 +99,18 @@ } } -#ifndef EVENTS_NO_RTOS - Thread::yield(); -#else - __WFI(); -#endif + if (exit) { + break; + } + + irq_wfi(); } } void EventQueue::trigger(struct event *e, int delay) { e->target = get_tick() + (unsigned)delay; - uint32_t primask = __get_PRIMASK(); - __disable_irq(); - + unsigned primask = irq_disable(); struct event *volatile *p = &_queue; while (*p && (*p)->target < e->target) { p = &(*p)->next; @@ -98,8 +118,7 @@ e->next = *p; *p = e; - - __set_PRIMASK(primask); + irq_enable(primask); } EventQueue::event *EventQueue::alloc(unsigned size, int ms) { @@ -109,27 +128,20 @@ struct event *e; - uint32_t primask = __get_PRIMASK(); - __disable_irq(); - + unsigned primask = irq_disable(); e = _free; if (e) { _free = e->next; } - - __set_PRIMASK(primask); + irq_enable(primask); return e; } void EventQueue::dealloc(struct event *e) { - uint32_t primask = __get_PRIMASK(); - __disable_irq(); - + unsigned primask = irq_disable(); e->next = _free; _free = e; - - __set_PRIMASK(primask); - + irq_enable(primask); }