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:
- 2:11cda6bead99
- Parent:
- 1:2202c19570e5
- Child:
- 5:9963a617f952
--- a/EventQueue.cpp Wed Apr 20 12:40:18 2016 -0500 +++ b/EventQueue.cpp Wed Apr 20 14:15:54 2016 -0500 @@ -1,40 +1,78 @@ -#include <EventQueue.h> -#include "mbed.h" +#include "EventQueue.h" +#include "Event.h" -static void wakeup() {} +EventQueue::EventQueue() { + _tick = 0; + _timer.start(); + _ticker.attach_us(this, &EventQueue::tick, (1 << 16) * 1000); +} + +unsigned EventQueue::get_tick() { + return _tick + (unsigned)_timer.read_ms(); +} + +void EventQueue::tick() { + _timer.reset(); + _tick += 1 << 16; +} + +void EventQueue::wakeup() { + +} void EventQueue::dispatch(int ms) { - mbed::Timer timer; mbed::Timeout timeout; - timer.start(); - timeout.attach_us(wakeup, ms * 1000); + struct event exit; + + if (ms >= 0) { + memset(&exit, 0, sizeof exit); + event_register(&exit, ms); + } while (true) { while (_queue) { - _queue->callback(_queue->data); + int diff = (int)(_queue->target - get_tick()); + if (diff > 0) { + timeout.attach_us(this, &EventQueue::wakeup, diff * 1000); + break; + } + + struct event *volatile e = _queue; _queue = _queue->next; - } + e->registered = false; + + if (e == &exit) { + return; + } - if (ms >= 0 && timer.read_ms() >= ms) { - break; + e->callback(e->data); + + if (e->period >= 0) { + event_register(e, e->period); + } } __WFI(); } } -void EventQueue::event_register(struct event *event) { +void EventQueue::event_register(struct event *event, int ms) { + if (event->registered) { + return; + } + + event->target = get_tick() + (unsigned)ms; + event->registered = true; + __disable_irq(); - for (struct event *volatile *p = &_queue;; p = &(*p)->next) { - if (!*p) { - event->next = 0; - *p = event; - break; - } else if (*p == event) { - break; - } + struct event *volatile *p = &_queue; + while (*p && (*p)->target < event->target) { + p = &(*p)->next; } + + event->next = *p; + *p = event; __enable_irq(); }