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:
- 14:5abf2ccf2dbf
- Parent:
- 10:62767e708bb6
- Child:
- 15:92d7c0b8a0f5
--- a/EventQueue.cpp Fri Apr 22 22:32:35 2016 -0500 +++ b/EventQueue.cpp Tue May 10 07:51:44 2016 -0500 @@ -7,13 +7,31 @@ #endif -EventQueue::EventQueue() { + +EventQueue::EventQueue(unsigned event_count, unsigned event_context) { + _event_context = sizeof(FuncPtr<void()>) + event_context; + unsigned event_size = sizeof(struct event) + _event_context; + _mem = malloc(event_count * event_size); + _free = (struct event*)_mem; + + if (_mem) { + for (unsigned i = 0; i < event_count-1; i++) { + ((struct event*)((char*)_mem + i*event_size))->next = + (struct event*)((char*)_mem + (i+1)*event_size); + } + ((struct event*)((char*)_mem + (event_count-1)*event_size))->next = 0; + } + _queue = 0; _tick = 0; _timer.start(); _ticker.attach_us(this, &EventQueue::tick, (1 << 16) * 1000); } +EventQueue::~EventQueue() { + free(_mem); +} + unsigned EventQueue::get_tick() { return _tick + (unsigned)_timer.read_ms(); } @@ -32,8 +50,7 @@ struct event exit; if (ms >= 0) { - memset(&exit, 0, sizeof exit); - event_register(&exit, ms); + trigger(&exit, ms); } while (true) { @@ -46,16 +63,17 @@ struct event *volatile e = _queue; _queue = _queue->next; - e->registered = false; if (e == &exit) { return; } - e->callback(e->data); + e->dispatch(reinterpret_cast<void *>(e + 1)); if (e->period >= 0) { - event_register(e, e->period); + trigger(e, e->period); + } else { + dealloc(e); } } @@ -67,39 +85,51 @@ } } -void EventQueue::event_register(struct event *event, int ms) { - if (event->registered) { - return; - } - - event->target = get_tick() + (unsigned)ms; - event->registered = true; +void EventQueue::trigger(struct event *e, int delay) { + e->target = get_tick() + (unsigned)delay; uint32_t primask = __get_PRIMASK(); __disable_irq(); struct event *volatile *p = &_queue; - while (*p && (*p)->target < event->target) { + while (*p && (*p)->target < e->target) { p = &(*p)->next; } - event->next = *p; - *p = event; + e->next = *p; + *p = e; __set_PRIMASK(primask); } -void EventQueue::event_unregister(struct event *event) { +EventQueue::event *EventQueue::alloc(unsigned size, int ms) { + if (size > _event_context) { + return 0; + } + + struct event *e; + uint32_t primask = __get_PRIMASK(); __disable_irq(); - for (struct event *volatile *p = &_queue; *p; p = &(*p)->next) { - if (*p == event) { - *p = event->next; - break; - } + e = _free; + if (e) { + _free = e->next; } __set_PRIMASK(primask); + + return e; } +void EventQueue::dealloc(struct event *e) { + uint32_t primask = __get_PRIMASK(); + __disable_irq(); + + e->next = _free; + _free = e; + + __set_PRIMASK(primask); + +} +