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.cpp@9:2b0910397844, 2016-04-22 (annotated)
- Committer:
- Christopher Haster
- Date:
- Fri Apr 22 02:21:25 2016 -0500
- Revision:
- 9:2b0910397844
- Parent:
- 7:dcd589b578ca
- Child:
- 10:62767e708bb6
Move to yield in loop when rtos is present
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Christopher Haster |
2:11cda6bead99 | 1 | #include "EventQueue.h" |
Christopher Haster |
2:11cda6bead99 | 2 | #include "Event.h" |
Christopher Haster |
0:b1b901ae3696 | 3 | |
Christopher Haster |
9:2b0910397844 | 4 | #ifndef EVENTS_NO_RTOS |
Christopher Haster |
9:2b0910397844 | 5 | #include "rtos.h" |
Christopher Haster |
9:2b0910397844 | 6 | #endif |
Christopher Haster |
9:2b0910397844 | 7 | |
Christopher Haster |
0:b1b901ae3696 | 8 | |
Christopher Haster |
2:11cda6bead99 | 9 | EventQueue::EventQueue() { |
Christopher Haster |
5:9963a617f952 | 10 | _queue = 0; |
Christopher Haster |
2:11cda6bead99 | 11 | _tick = 0; |
Christopher Haster |
2:11cda6bead99 | 12 | _timer.start(); |
Christopher Haster |
2:11cda6bead99 | 13 | _ticker.attach_us(this, &EventQueue::tick, (1 << 16) * 1000); |
Christopher Haster |
2:11cda6bead99 | 14 | } |
Christopher Haster |
2:11cda6bead99 | 15 | |
Christopher Haster |
2:11cda6bead99 | 16 | unsigned EventQueue::get_tick() { |
Christopher Haster |
2:11cda6bead99 | 17 | return _tick + (unsigned)_timer.read_ms(); |
Christopher Haster |
2:11cda6bead99 | 18 | } |
Christopher Haster |
2:11cda6bead99 | 19 | |
Christopher Haster |
2:11cda6bead99 | 20 | void EventQueue::tick() { |
Christopher Haster |
2:11cda6bead99 | 21 | _timer.reset(); |
Christopher Haster |
2:11cda6bead99 | 22 | _tick += 1 << 16; |
Christopher Haster |
2:11cda6bead99 | 23 | } |
Christopher Haster |
2:11cda6bead99 | 24 | |
Christopher Haster |
2:11cda6bead99 | 25 | void EventQueue::wakeup() { |
Christopher Haster |
2:11cda6bead99 | 26 | |
Christopher Haster |
2:11cda6bead99 | 27 | } |
Christopher Haster |
0:b1b901ae3696 | 28 | |
Christopher Haster |
1:2202c19570e5 | 29 | void EventQueue::dispatch(int ms) { |
Christopher Haster |
0:b1b901ae3696 | 30 | mbed::Timeout timeout; |
Christopher Haster |
2:11cda6bead99 | 31 | struct event exit; |
Christopher Haster |
2:11cda6bead99 | 32 | |
Christopher Haster |
2:11cda6bead99 | 33 | if (ms >= 0) { |
Christopher Haster |
2:11cda6bead99 | 34 | memset(&exit, 0, sizeof exit); |
Christopher Haster |
2:11cda6bead99 | 35 | event_register(&exit, ms); |
Christopher Haster |
2:11cda6bead99 | 36 | } |
Christopher Haster |
0:b1b901ae3696 | 37 | |
Christopher Haster |
0:b1b901ae3696 | 38 | while (true) { |
Christopher Haster |
0:b1b901ae3696 | 39 | while (_queue) { |
Christopher Haster |
2:11cda6bead99 | 40 | int diff = (int)(_queue->target - get_tick()); |
Christopher Haster |
2:11cda6bead99 | 41 | if (diff > 0) { |
Christopher Haster |
2:11cda6bead99 | 42 | timeout.attach_us(this, &EventQueue::wakeup, diff * 1000); |
Christopher Haster |
2:11cda6bead99 | 43 | break; |
Christopher Haster |
2:11cda6bead99 | 44 | } |
Christopher Haster |
2:11cda6bead99 | 45 | |
Christopher Haster |
2:11cda6bead99 | 46 | struct event *volatile e = _queue; |
Christopher Haster |
0:b1b901ae3696 | 47 | _queue = _queue->next; |
Christopher Haster |
2:11cda6bead99 | 48 | e->registered = false; |
Christopher Haster |
2:11cda6bead99 | 49 | |
Christopher Haster |
2:11cda6bead99 | 50 | if (e == &exit) { |
Christopher Haster |
2:11cda6bead99 | 51 | return; |
Christopher Haster |
2:11cda6bead99 | 52 | } |
Christopher Haster |
0:b1b901ae3696 | 53 | |
Christopher Haster |
2:11cda6bead99 | 54 | e->callback(e->data); |
Christopher Haster |
2:11cda6bead99 | 55 | |
Christopher Haster |
2:11cda6bead99 | 56 | if (e->period >= 0) { |
Christopher Haster |
2:11cda6bead99 | 57 | event_register(e, e->period); |
Christopher Haster |
2:11cda6bead99 | 58 | } |
Christopher Haster |
0:b1b901ae3696 | 59 | } |
Christopher Haster |
0:b1b901ae3696 | 60 | |
Christopher Haster |
9:2b0910397844 | 61 | #ifndef EVENTS_NO_RTOS |
Christopher Haster |
9:2b0910397844 | 62 | Thread::yield(); |
Christopher Haster |
9:2b0910397844 | 63 | #else |
Christopher Haster |
0:b1b901ae3696 | 64 | __WFI(); |
Christopher Haster |
9:2b0910397844 | 65 | #endif |
Christopher Haster |
0:b1b901ae3696 | 66 | } |
Christopher Haster |
0:b1b901ae3696 | 67 | } |
Christopher Haster |
0:b1b901ae3696 | 68 | |
Christopher Haster |
2:11cda6bead99 | 69 | void EventQueue::event_register(struct event *event, int ms) { |
Christopher Haster |
2:11cda6bead99 | 70 | if (event->registered) { |
Christopher Haster |
2:11cda6bead99 | 71 | return; |
Christopher Haster |
2:11cda6bead99 | 72 | } |
Christopher Haster |
2:11cda6bead99 | 73 | |
Christopher Haster |
2:11cda6bead99 | 74 | event->target = get_tick() + (unsigned)ms; |
Christopher Haster |
2:11cda6bead99 | 75 | event->registered = true; |
Christopher Haster |
2:11cda6bead99 | 76 | |
Christopher Haster |
6:31c141d3bcc7 | 77 | uint32_t primask = __get_PRIMASK(); |
Christopher Haster |
0:b1b901ae3696 | 78 | __disable_irq(); |
Christopher Haster |
6:31c141d3bcc7 | 79 | |
Christopher Haster |
2:11cda6bead99 | 80 | struct event *volatile *p = &_queue; |
Christopher Haster |
2:11cda6bead99 | 81 | while (*p && (*p)->target < event->target) { |
Christopher Haster |
2:11cda6bead99 | 82 | p = &(*p)->next; |
Christopher Haster |
0:b1b901ae3696 | 83 | } |
Christopher Haster |
2:11cda6bead99 | 84 | |
Christopher Haster |
2:11cda6bead99 | 85 | event->next = *p; |
Christopher Haster |
2:11cda6bead99 | 86 | *p = event; |
Christopher Haster |
6:31c141d3bcc7 | 87 | |
Christopher Haster |
7:dcd589b578ca | 88 | __set_PRIMASK(primask); |
Christopher Haster |
0:b1b901ae3696 | 89 | } |
Christopher Haster |
0:b1b901ae3696 | 90 | |
Christopher Haster |
0:b1b901ae3696 | 91 | void EventQueue::event_unregister(struct event *event) { |
Christopher Haster |
6:31c141d3bcc7 | 92 | uint32_t primask = __get_PRIMASK(); |
Christopher Haster |
0:b1b901ae3696 | 93 | __disable_irq(); |
Christopher Haster |
6:31c141d3bcc7 | 94 | |
Christopher Haster |
1:2202c19570e5 | 95 | for (struct event *volatile *p = &_queue; *p; p = &(*p)->next) { |
Christopher Haster |
0:b1b901ae3696 | 96 | if (*p == event) { |
Christopher Haster |
0:b1b901ae3696 | 97 | *p = event->next; |
Christopher Haster |
0:b1b901ae3696 | 98 | break; |
Christopher Haster |
0:b1b901ae3696 | 99 | } |
Christopher Haster |
0:b1b901ae3696 | 100 | } |
Christopher Haster |
6:31c141d3bcc7 | 101 | |
Christopher Haster |
7:dcd589b578ca | 102 | __set_PRIMASK(primask); |
Christopher Haster |
0:b1b901ae3696 | 103 | } |
Christopher Haster |
0:b1b901ae3696 | 104 |