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:
- 16:ff5d48fcce1b
- Parent:
- 15:92d7c0b8a0f5
- Child:
- 17:6d564266850e
--- a/EventQueue.cpp Tue May 10 09:23:27 2016 -0500 +++ b/EventQueue.cpp Mon Apr 18 09:47:21 2016 -0500 @@ -1,10 +1,7 @@ #include "EventQueue.h" #include "Event.h" #include "mbed.h" - -#ifndef EVENTS_NO_RTOS #include "rtos.h" -#endif // Platform specific definitions @@ -18,14 +15,6 @@ __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) { @@ -56,39 +45,28 @@ return _tick + (unsigned)_timer.read_ms(); } +bool EventQueue::past_tick(unsigned tick) { + return static_cast<int>(tick - get_tick()) <= 0; +} + void EventQueue::tick() { _timer.reset(); _tick += 1 << 16; } -void EventQueue::wakeup() { - -} - -void EventQueue::exit(volatile bool *exit) { - *exit = true; -} - void EventQueue::dispatch(int ms) { - Timeout timeout; - volatile bool exit = false; - - if (ms >= 0) { - Event<void(volatile bool*)> e(this, this, &EventQueue::exit); - e.delay(ms); - e.trigger(&exit); - } + unsigned target = get_tick() + (unsigned)ms; while (true) { while (_queue) { - int diff = (int)(_queue->target - get_tick()); - if (diff > 0) { - timeout.attach_us(this, &EventQueue::wakeup, diff * 1000); + if (!past_tick(_queue->target)) { break; } + unsigned primask = irq_disable(); struct event *volatile e = _queue; _queue = _queue->next; + irq_enable(primask); e->dispatch(reinterpret_cast<void *>(e + 1)); @@ -99,11 +77,14 @@ } } - if (exit) { - break; + if (ms >= 0 && past_tick(target)) { + return; } - irq_wfi(); + osStatus status = Thread::yield(); + if (status != osOK) { + return; + } } } @@ -126,16 +107,28 @@ return 0; } + unsigned target = get_tick() + (unsigned)ms; struct event *e; - unsigned primask = irq_disable(); - e = _free; - if (e) { - _free = e->next; + while (true) { + if (_free) { + unsigned primask = irq_disable(); + if (_free) { + e = _free; + _free = _free->next; + } + irq_enable(primask); + } + + if (e || (ms >= 0 && past_tick(target))) { + return e; + } + + osStatus status = Thread::yield(); + if (status != osOK) { + return e; + } } - irq_enable(primask); - - return e; } void EventQueue::dealloc(struct event *e) {