Kev Mann / mbed-dev-OS5_10_4
Committer:
kevman
Date:
Wed Mar 13 11:03:24 2019 +0000
Revision:
2:7aab896b1a3b
Parent:
0:38ceb79fef03
2019-03-13

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kevman 0:38ceb79fef03 1 ## The mbed-events library ##
kevman 0:38ceb79fef03 2
kevman 0:38ceb79fef03 3 The mbed-events library provides a flexible queue for scheduling events.
kevman 0:38ceb79fef03 4
kevman 0:38ceb79fef03 5 ``` cpp
kevman 0:38ceb79fef03 6 #include "mbed_events.h"
kevman 0:38ceb79fef03 7 #include <stdio.h>
kevman 0:38ceb79fef03 8
kevman 0:38ceb79fef03 9 int main() {
kevman 0:38ceb79fef03 10 // creates a queue with the default size
kevman 0:38ceb79fef03 11 EventQueue queue;
kevman 0:38ceb79fef03 12
kevman 0:38ceb79fef03 13 // events are simple callbacks
kevman 0:38ceb79fef03 14 queue.call(printf, "called immediately\n");
kevman 0:38ceb79fef03 15 queue.call_in(2000, printf, "called in 2 seconds\n");
kevman 0:38ceb79fef03 16 queue.call_every(1000, printf, "called every 1 seconds\n");
kevman 0:38ceb79fef03 17
kevman 0:38ceb79fef03 18 // events are executed by the dispatch method
kevman 0:38ceb79fef03 19 queue.dispatch();
kevman 0:38ceb79fef03 20 }
kevman 0:38ceb79fef03 21 ```
kevman 0:38ceb79fef03 22
kevman 0:38ceb79fef03 23 The mbed-events library can be used as a normal event loop, or it can be
kevman 0:38ceb79fef03 24 backgrounded on a single hardware timer or even another event loop. It is
kevman 0:38ceb79fef03 25 both thread and irq safe, and provides functions for easily composing
kevman 0:38ceb79fef03 26 independent event queues.
kevman 0:38ceb79fef03 27
kevman 0:38ceb79fef03 28 The mbed-events library can act as a drop-in scheduler, provide synchronization
kevman 0:38ceb79fef03 29 between multiple threads, or just act as a mechanism for moving events out of
kevman 0:38ceb79fef03 30 interrupt contexts.
kevman 0:38ceb79fef03 31
kevman 0:38ceb79fef03 32 ### Usage ###
kevman 0:38ceb79fef03 33
kevman 0:38ceb79fef03 34 The core of the mbed-events library is the [EventQueue](EventQueue.h) class,
kevman 0:38ceb79fef03 35 which represents a single event queue. The `EventQueue::dispatch` function
kevman 0:38ceb79fef03 36 runs the queue, providing the context for executing events.
kevman 0:38ceb79fef03 37
kevman 0:38ceb79fef03 38 ``` cpp
kevman 0:38ceb79fef03 39 // Creates an event queue enough buffer space for 32 Callbacks. This
kevman 0:38ceb79fef03 40 // is the default if no argument was provided. Alternatively the size
kevman 0:38ceb79fef03 41 // can just be specified in bytes.
kevman 0:38ceb79fef03 42 EventQueue queue(32*EVENTS_EVENT_SIZE);
kevman 0:38ceb79fef03 43
kevman 0:38ceb79fef03 44 // Events can be posted to the underlying event queue with dynamic
kevman 0:38ceb79fef03 45 // context allocated from the specified buffer
kevman 0:38ceb79fef03 46 queue.call(printf, "hello %d %d %d %d\n", 1, 2, 3, 4);
kevman 0:38ceb79fef03 47 queue.call(&serial, &Serial::printf, "hi\n");
kevman 0:38ceb79fef03 48
kevman 0:38ceb79fef03 49 // The dispatch function provides the context for the running the queue
kevman 0:38ceb79fef03 50 // and can take a millisecond timeout to run for a fixed time or to just
kevman 0:38ceb79fef03 51 // dispatch any pending events
kevman 0:38ceb79fef03 52 queue.dispatch();
kevman 0:38ceb79fef03 53 ```
kevman 0:38ceb79fef03 54
kevman 0:38ceb79fef03 55 The EventQueue class provides several call functions for posting events
kevman 0:38ceb79fef03 56 to the underlying event queue. The call functions are thread and irq safe,
kevman 0:38ceb79fef03 57 don't need the underlying loop to be running, and provide an easy mechanism
kevman 0:38ceb79fef03 58 for moving events out of interrupt contexts.
kevman 0:38ceb79fef03 59
kevman 0:38ceb79fef03 60 ``` cpp
kevman 0:38ceb79fef03 61 // Simple call function registers events to be called as soon as possible
kevman 0:38ceb79fef03 62 queue.call(doit);
kevman 0:38ceb79fef03 63 queue.call(printf, "called immediately\n");
kevman 0:38ceb79fef03 64
kevman 0:38ceb79fef03 65 // The call_in function registers events to be called after a delay
kevman 0:38ceb79fef03 66 // specified in milliseconds
kevman 0:38ceb79fef03 67 queue.call_in(2000, doit_in_two_seconds);
kevman 0:38ceb79fef03 68 queue.call_in(300, printf, "called in 0.3 seconds\n");
kevman 0:38ceb79fef03 69
kevman 0:38ceb79fef03 70 // The call_every function registers events to be called repeatedly
kevman 0:38ceb79fef03 71 // with a period specified in milliseconds
kevman 0:38ceb79fef03 72 queue.call_every(2000, doit_every_two_seconds);
kevman 0:38ceb79fef03 73 queue.call_every(400, printf, "called every 0.4 seconds\n");
kevman 0:38ceb79fef03 74 ```
kevman 0:38ceb79fef03 75
kevman 0:38ceb79fef03 76 The call functions return an id that uniquely represents the event in the
kevman 0:38ceb79fef03 77 the event queue. This id can be passed to `EventQueue::cancel` to cancel
kevman 0:38ceb79fef03 78 an in-flight event.
kevman 0:38ceb79fef03 79
kevman 0:38ceb79fef03 80 ``` cpp
kevman 0:38ceb79fef03 81 // The event id uniquely represents the event in the queue
kevman 0:38ceb79fef03 82 int id = queue.call_in(100, printf, "will this work?\n");
kevman 0:38ceb79fef03 83
kevman 0:38ceb79fef03 84 // If there was not enough memory necessary to allocate the event,
kevman 0:38ceb79fef03 85 // an id of 0 is returned from the call functions
kevman 0:38ceb79fef03 86 if (id) {
kevman 0:38ceb79fef03 87 error("oh no!");
kevman 0:38ceb79fef03 88 }
kevman 0:38ceb79fef03 89
kevman 0:38ceb79fef03 90 // Events can be cancelled as long as they have not been dispatched. If the
kevman 0:38ceb79fef03 91 // event has already expired, cancel has no side-effects.
kevman 0:38ceb79fef03 92 queue.cancel(id);
kevman 0:38ceb79fef03 93 ```
kevman 0:38ceb79fef03 94
kevman 0:38ceb79fef03 95 For a more fine-grain control of event dispatch, the `Event` class can be
kevman 0:38ceb79fef03 96 manually instantiated and configured. An `Event` represents an event as
kevman 0:38ceb79fef03 97 a C++ style function object and can be directly passed to other APIs that
kevman 0:38ceb79fef03 98 expect a callback.
kevman 0:38ceb79fef03 99
kevman 0:38ceb79fef03 100 ``` cpp
kevman 0:38ceb79fef03 101 // Creates an event bound to the specified event queue
kevman 0:38ceb79fef03 102 EventQueue queue;
kevman 0:38ceb79fef03 103 Event<void()> event(&queue, doit);
kevman 0:38ceb79fef03 104
kevman 0:38ceb79fef03 105 // The event can be manually configured for special timing requirements
kevman 0:38ceb79fef03 106 // specified in milliseconds
kevman 0:38ceb79fef03 107 event.delay(10);
kevman 0:38ceb79fef03 108 event.period(10000);
kevman 0:38ceb79fef03 109
kevman 0:38ceb79fef03 110 // Posted events are dispatched in the context of the queue's
kevman 0:38ceb79fef03 111 // dispatch function
kevman 0:38ceb79fef03 112 queue.dispatch();
kevman 0:38ceb79fef03 113
kevman 0:38ceb79fef03 114 // Events can also pass arguments to the underlying callback when both
kevman 0:38ceb79fef03 115 // initially constructed and posted.
kevman 0:38ceb79fef03 116 Event<void(int, int)> event(&queue, printf, "received %d and %d\n");
kevman 0:38ceb79fef03 117
kevman 0:38ceb79fef03 118 // Events can be posted multiple times and enqueue gracefully until
kevman 0:38ceb79fef03 119 // the dispatch function is called.
kevman 0:38ceb79fef03 120 event.post(1, 2);
kevman 0:38ceb79fef03 121 event.post(3, 4);
kevman 0:38ceb79fef03 122 event.post(5, 6);
kevman 0:38ceb79fef03 123
kevman 0:38ceb79fef03 124 queue.dispatch();
kevman 0:38ceb79fef03 125 ```
kevman 0:38ceb79fef03 126
kevman 0:38ceb79fef03 127 Event queues easily align with module boundaries, where internal state can
kevman 0:38ceb79fef03 128 be implicitly synchronized through event dispatch. Multiple modules can
kevman 0:38ceb79fef03 129 use independent event queues, but still be composed through the
kevman 0:38ceb79fef03 130 `EventQueue::chain` function.
kevman 0:38ceb79fef03 131
kevman 0:38ceb79fef03 132 ``` cpp
kevman 0:38ceb79fef03 133 // Create some event queues with pending events
kevman 0:38ceb79fef03 134 EventQueue a;
kevman 0:38ceb79fef03 135 a.call(printf, "hello from a!\n");
kevman 0:38ceb79fef03 136
kevman 0:38ceb79fef03 137 EventQueue b;
kevman 0:38ceb79fef03 138 b.call(printf, "hello from b!\n");
kevman 0:38ceb79fef03 139
kevman 0:38ceb79fef03 140 EventQueue c;
kevman 0:38ceb79fef03 141 c.call(printf, "hello from c!\n");
kevman 0:38ceb79fef03 142
kevman 0:38ceb79fef03 143 // Chain c and b onto a's event queue. Both c and b will be dispatched
kevman 0:38ceb79fef03 144 // in the context of a's dispatch function.
kevman 0:38ceb79fef03 145 c.chain(&a);
kevman 0:38ceb79fef03 146 b.chain(&a);
kevman 0:38ceb79fef03 147
kevman 0:38ceb79fef03 148 // Dispatching a will in turn dispatch b and c, printing hello from
kevman 0:38ceb79fef03 149 // all three queues
kevman 0:38ceb79fef03 150 a.dispatch();
kevman 0:38ceb79fef03 151 ```
kevman 0:38ceb79fef03 152
kevman 0:38ceb79fef03 153