This is a fork of the `events` subdirectory of https://github.com/ARMmbed/mbed-os

Dependents:   HelloWorld_CCA01M1 HelloWorld_CCA02M1 CI-data-logger-server HelloWorld_CCA02M1 ... more

This is a fork of the events subdirectory of https://github.com/ARMmbed/mbed-os.

Note, you must import this library with import name: events!!!

Committer:
Sam Grove
Date:
Sat Oct 01 02:11:36 2016 -0500
Revision:
2:a60d8117d0e0
Parent:
0:a792d4bf36c2
Child:
5:705843a08e16
For drivers, events, hal, platform, rtos and mbed.h add one level of path to make sure specific and unique includes files are found.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Bogdan Marinescu 0:a792d4bf36c2 1 /*
Bogdan Marinescu 0:a792d4bf36c2 2 * Flexible event queue for dispatching events
Bogdan Marinescu 0:a792d4bf36c2 3 *
Bogdan Marinescu 0:a792d4bf36c2 4 * Copyright (c) 2016 Christopher Haster
Bogdan Marinescu 0:a792d4bf36c2 5 *
Bogdan Marinescu 0:a792d4bf36c2 6 * Licensed under the Apache License, Version 2.0 (the "License");
Bogdan Marinescu 0:a792d4bf36c2 7 * you may not use this file except in compliance with the License.
Bogdan Marinescu 0:a792d4bf36c2 8 * You may obtain a copy of the License at
Bogdan Marinescu 0:a792d4bf36c2 9 *
Bogdan Marinescu 0:a792d4bf36c2 10 * http://www.apache.org/licenses/LICENSE-2.0
Bogdan Marinescu 0:a792d4bf36c2 11 *
Bogdan Marinescu 0:a792d4bf36c2 12 * Unless required by applicable law or agreed to in writing, software
Bogdan Marinescu 0:a792d4bf36c2 13 * distributed under the License is distributed on an "AS IS" BASIS,
Bogdan Marinescu 0:a792d4bf36c2 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Bogdan Marinescu 0:a792d4bf36c2 15 * See the License for the specific language governing permissions and
Bogdan Marinescu 0:a792d4bf36c2 16 * limitations under the License.
Bogdan Marinescu 0:a792d4bf36c2 17 */
Bogdan Marinescu 0:a792d4bf36c2 18 #ifndef EQUEUE_H
Bogdan Marinescu 0:a792d4bf36c2 19 #define EQUEUE_H
Bogdan Marinescu 0:a792d4bf36c2 20
Bogdan Marinescu 0:a792d4bf36c2 21 #ifdef __cplusplus
Bogdan Marinescu 0:a792d4bf36c2 22 extern "C" {
Bogdan Marinescu 0:a792d4bf36c2 23 #endif
Bogdan Marinescu 0:a792d4bf36c2 24
Bogdan Marinescu 0:a792d4bf36c2 25 // Platform specific files
Sam Grove 2:a60d8117d0e0 26 #include "equeue/equeue_platform.h"
Bogdan Marinescu 0:a792d4bf36c2 27
Bogdan Marinescu 0:a792d4bf36c2 28 #include <stddef.h>
Bogdan Marinescu 0:a792d4bf36c2 29 #include <stdint.h>
Bogdan Marinescu 0:a792d4bf36c2 30
Bogdan Marinescu 0:a792d4bf36c2 31
Bogdan Marinescu 0:a792d4bf36c2 32 // The minimum size of an event
Bogdan Marinescu 0:a792d4bf36c2 33 // This size is guaranteed to fit events created by event_call
Bogdan Marinescu 0:a792d4bf36c2 34 #define EQUEUE_EVENT_SIZE (sizeof(struct equeue_event) + 2*sizeof(void*))
Bogdan Marinescu 0:a792d4bf36c2 35
Bogdan Marinescu 0:a792d4bf36c2 36 // Internal event structure
Bogdan Marinescu 0:a792d4bf36c2 37 struct equeue_event {
Bogdan Marinescu 0:a792d4bf36c2 38 unsigned size;
Bogdan Marinescu 0:a792d4bf36c2 39 uint8_t id;
Bogdan Marinescu 0:a792d4bf36c2 40 uint8_t generation;
Bogdan Marinescu 0:a792d4bf36c2 41
Bogdan Marinescu 0:a792d4bf36c2 42 struct equeue_event *next;
Bogdan Marinescu 0:a792d4bf36c2 43 struct equeue_event *sibling;
Bogdan Marinescu 0:a792d4bf36c2 44 struct equeue_event **ref;
Bogdan Marinescu 0:a792d4bf36c2 45
Bogdan Marinescu 0:a792d4bf36c2 46 unsigned target;
Bogdan Marinescu 0:a792d4bf36c2 47 int period;
Bogdan Marinescu 0:a792d4bf36c2 48 void (*dtor)(void *);
Bogdan Marinescu 0:a792d4bf36c2 49
Bogdan Marinescu 0:a792d4bf36c2 50 void (*cb)(void *);
Bogdan Marinescu 0:a792d4bf36c2 51 // data follows
Bogdan Marinescu 0:a792d4bf36c2 52 };
Bogdan Marinescu 0:a792d4bf36c2 53
Bogdan Marinescu 0:a792d4bf36c2 54 // Event queue structure
Bogdan Marinescu 0:a792d4bf36c2 55 typedef struct equeue {
Bogdan Marinescu 0:a792d4bf36c2 56 struct equeue_event *queue;
Bogdan Marinescu 0:a792d4bf36c2 57 unsigned tick;
Bogdan Marinescu 0:a792d4bf36c2 58 unsigned breaks;
Bogdan Marinescu 0:a792d4bf36c2 59 uint8_t generation;
Bogdan Marinescu 0:a792d4bf36c2 60
Bogdan Marinescu 0:a792d4bf36c2 61 unsigned char *buffer;
Bogdan Marinescu 0:a792d4bf36c2 62 unsigned npw2;
Bogdan Marinescu 0:a792d4bf36c2 63 void *allocated;
Bogdan Marinescu 0:a792d4bf36c2 64
Bogdan Marinescu 0:a792d4bf36c2 65 struct equeue_event *chunks;
Bogdan Marinescu 0:a792d4bf36c2 66 struct equeue_slab {
Bogdan Marinescu 0:a792d4bf36c2 67 size_t size;
Bogdan Marinescu 0:a792d4bf36c2 68 unsigned char *data;
Bogdan Marinescu 0:a792d4bf36c2 69 } slab;
Bogdan Marinescu 0:a792d4bf36c2 70
Bogdan Marinescu 0:a792d4bf36c2 71 struct equeue_background {
Bogdan Marinescu 0:a792d4bf36c2 72 bool active;
Bogdan Marinescu 0:a792d4bf36c2 73 void (*update)(void *timer, int ms);
Bogdan Marinescu 0:a792d4bf36c2 74 void *timer;
Bogdan Marinescu 0:a792d4bf36c2 75 } background;
Bogdan Marinescu 0:a792d4bf36c2 76
Bogdan Marinescu 0:a792d4bf36c2 77 equeue_sema_t eventsema;
Bogdan Marinescu 0:a792d4bf36c2 78 equeue_mutex_t queuelock;
Bogdan Marinescu 0:a792d4bf36c2 79 equeue_mutex_t memlock;
Bogdan Marinescu 0:a792d4bf36c2 80 } equeue_t;
Bogdan Marinescu 0:a792d4bf36c2 81
Bogdan Marinescu 0:a792d4bf36c2 82
Bogdan Marinescu 0:a792d4bf36c2 83 // Queue lifetime operations
Bogdan Marinescu 0:a792d4bf36c2 84 //
Bogdan Marinescu 0:a792d4bf36c2 85 // Creates and destroys an event queue. The event queue either allocates a
Bogdan Marinescu 0:a792d4bf36c2 86 // buffer of the specified size with malloc or uses a user provided buffer
Bogdan Marinescu 0:a792d4bf36c2 87 // if constructed with equeue_create_inplace.
Bogdan Marinescu 0:a792d4bf36c2 88 //
Bogdan Marinescu 0:a792d4bf36c2 89 // If the event queue creation fails, equeue_create returns a negative,
Bogdan Marinescu 0:a792d4bf36c2 90 // platform-specific error code.
Bogdan Marinescu 0:a792d4bf36c2 91 int equeue_create(equeue_t *queue, size_t size);
Bogdan Marinescu 0:a792d4bf36c2 92 int equeue_create_inplace(equeue_t *queue, size_t size, void *buffer);
Bogdan Marinescu 0:a792d4bf36c2 93 void equeue_destroy(equeue_t *queue);
Bogdan Marinescu 0:a792d4bf36c2 94
Bogdan Marinescu 0:a792d4bf36c2 95 // Dispatch events
Bogdan Marinescu 0:a792d4bf36c2 96 //
Bogdan Marinescu 0:a792d4bf36c2 97 // Executes events until the specified milliseconds have passed. If ms is
Bogdan Marinescu 0:a792d4bf36c2 98 // negative, equeue_dispatch will dispatch events indefinitely or until
Bogdan Marinescu 0:a792d4bf36c2 99 // equeue_break is called on this queue.
Bogdan Marinescu 0:a792d4bf36c2 100 //
Bogdan Marinescu 0:a792d4bf36c2 101 // When called with a finite timeout, the equeue_dispatch function is
Bogdan Marinescu 0:a792d4bf36c2 102 // guaranteed to terminate. When called with a timeout of 0, the
Bogdan Marinescu 0:a792d4bf36c2 103 // equeue_dispatch does not wait and is irq safe.
Bogdan Marinescu 0:a792d4bf36c2 104 void equeue_dispatch(equeue_t *queue, int ms);
Bogdan Marinescu 0:a792d4bf36c2 105
Bogdan Marinescu 0:a792d4bf36c2 106 // Break out of a running event loop
Bogdan Marinescu 0:a792d4bf36c2 107 //
Bogdan Marinescu 0:a792d4bf36c2 108 // Forces the specified event queue's dispatch loop to terminate. Pending
Bogdan Marinescu 0:a792d4bf36c2 109 // events may finish executing, but no new events will be executed.
Bogdan Marinescu 0:a792d4bf36c2 110 void equeue_break(equeue_t *queue);
Bogdan Marinescu 0:a792d4bf36c2 111
Bogdan Marinescu 0:a792d4bf36c2 112 // Simple event calls
Bogdan Marinescu 0:a792d4bf36c2 113 //
Bogdan Marinescu 0:a792d4bf36c2 114 // The specified callback will be executed in the context of the event queue's
Bogdan Marinescu 0:a792d4bf36c2 115 // dispatch loop. When the callback is executed depends on the call function.
Bogdan Marinescu 0:a792d4bf36c2 116 //
Bogdan Marinescu 0:a792d4bf36c2 117 // equeue_call - Immediately post an event to the queue
Bogdan Marinescu 0:a792d4bf36c2 118 // equeue_call_in - Post an event after a specified time in milliseconds
Bogdan Marinescu 0:a792d4bf36c2 119 // equeue_call_every - Post an event periodically every milliseconds
Bogdan Marinescu 0:a792d4bf36c2 120 //
Bogdan Marinescu 0:a792d4bf36c2 121 // All equeue_call functions are irq safe and can act as a mechanism for
Bogdan Marinescu 0:a792d4bf36c2 122 // moving events out of irq contexts.
Bogdan Marinescu 0:a792d4bf36c2 123 //
Bogdan Marinescu 0:a792d4bf36c2 124 // The return value is a unique id that represents the posted event and can
Bogdan Marinescu 0:a792d4bf36c2 125 // be passed to equeue_cancel. If there is not enough memory to allocate the
Bogdan Marinescu 0:a792d4bf36c2 126 // event, equeue_call returns an id of 0.
Bogdan Marinescu 0:a792d4bf36c2 127 int equeue_call(equeue_t *queue, void (*cb)(void *), void *data);
Bogdan Marinescu 0:a792d4bf36c2 128 int equeue_call_in(equeue_t *queue, int ms, void (*cb)(void *), void *data);
Bogdan Marinescu 0:a792d4bf36c2 129 int equeue_call_every(equeue_t *queue, int ms, void (*cb)(void *), void *data);
Bogdan Marinescu 0:a792d4bf36c2 130
Bogdan Marinescu 0:a792d4bf36c2 131 // Allocate memory for events
Bogdan Marinescu 0:a792d4bf36c2 132 //
Bogdan Marinescu 0:a792d4bf36c2 133 // The equeue_alloc function allocates an event that can be manually dispatched
Bogdan Marinescu 0:a792d4bf36c2 134 // with equeue_post. The equeue_dealloc function may be used to free an event
Bogdan Marinescu 0:a792d4bf36c2 135 // that has not been posted. Once posted, an event's memory is managed by the
Bogdan Marinescu 0:a792d4bf36c2 136 // event queue and should not be deallocated.
Bogdan Marinescu 0:a792d4bf36c2 137 //
Bogdan Marinescu 0:a792d4bf36c2 138 // Both equeue_alloc and equeue_dealloc are irq safe.
Bogdan Marinescu 0:a792d4bf36c2 139 //
Bogdan Marinescu 0:a792d4bf36c2 140 // The equeue allocator is designed to minimize jitter in interrupt contexts as
Bogdan Marinescu 0:a792d4bf36c2 141 // well as avoid memory fragmentation on small devices. The allocator achieves
Bogdan Marinescu 0:a792d4bf36c2 142 // both constant-runtime and zero-fragmentation for fixed-size events, however
Bogdan Marinescu 0:a792d4bf36c2 143 // grows linearly as the quantity of different sized allocations increases.
Bogdan Marinescu 0:a792d4bf36c2 144 //
Bogdan Marinescu 0:a792d4bf36c2 145 // The equeue_alloc function returns a pointer to the event's allocated memory
Bogdan Marinescu 0:a792d4bf36c2 146 // and acts as a handle to the underlying event. If there is not enough memory
Bogdan Marinescu 0:a792d4bf36c2 147 // to allocate the event, equeue_alloc returns null.
Bogdan Marinescu 0:a792d4bf36c2 148 void *equeue_alloc(equeue_t *queue, size_t size);
Bogdan Marinescu 0:a792d4bf36c2 149 void equeue_dealloc(equeue_t *queue, void *event);
Bogdan Marinescu 0:a792d4bf36c2 150
Bogdan Marinescu 0:a792d4bf36c2 151 // Configure an allocated event
Bogdan Marinescu 0:a792d4bf36c2 152 //
Bogdan Marinescu 0:a792d4bf36c2 153 // equeue_event_delay - Millisecond delay before dispatching an event
Bogdan Marinescu 0:a792d4bf36c2 154 // equeue_event_period - Millisecond period for repeating dispatching an event
Bogdan Marinescu 0:a792d4bf36c2 155 // equeue_event_dtor - Destructor to run when the event is deallocated
Bogdan Marinescu 0:a792d4bf36c2 156 void equeue_event_delay(void *event, int ms);
Bogdan Marinescu 0:a792d4bf36c2 157 void equeue_event_period(void *event, int ms);
Bogdan Marinescu 0:a792d4bf36c2 158 void equeue_event_dtor(void *event, void (*dtor)(void *));
Bogdan Marinescu 0:a792d4bf36c2 159
Bogdan Marinescu 0:a792d4bf36c2 160 // Post an event onto the event queue
Bogdan Marinescu 0:a792d4bf36c2 161 //
Bogdan Marinescu 0:a792d4bf36c2 162 // The equeue_post function takes a callback and a pointer to an event
Bogdan Marinescu 0:a792d4bf36c2 163 // allocated by equeue_alloc. The specified callback will be executed in the
Bogdan Marinescu 0:a792d4bf36c2 164 // context of the event queue's dispatch loop with the allocated event
Bogdan Marinescu 0:a792d4bf36c2 165 // as its argument.
Bogdan Marinescu 0:a792d4bf36c2 166 //
Bogdan Marinescu 0:a792d4bf36c2 167 // The equeue_post function is irq safe and can act as a mechanism for
Bogdan Marinescu 0:a792d4bf36c2 168 // moving events out of irq contexts.
Bogdan Marinescu 0:a792d4bf36c2 169 //
Bogdan Marinescu 0:a792d4bf36c2 170 // The return value is a unique id that represents the posted event and can
Bogdan Marinescu 0:a792d4bf36c2 171 // be passed to equeue_cancel.
Bogdan Marinescu 0:a792d4bf36c2 172 int equeue_post(equeue_t *queue, void (*cb)(void *), void *event);
Bogdan Marinescu 0:a792d4bf36c2 173
Bogdan Marinescu 0:a792d4bf36c2 174 // Cancel an in-flight event
Bogdan Marinescu 0:a792d4bf36c2 175 //
Bogdan Marinescu 0:a792d4bf36c2 176 // Attempts to cancel an event referenced by the unique id returned from
Bogdan Marinescu 0:a792d4bf36c2 177 // equeue_call or equeue_post. It is safe to call equeue_cancel after an event
Bogdan Marinescu 0:a792d4bf36c2 178 // has already been dispatched.
Bogdan Marinescu 0:a792d4bf36c2 179 //
Bogdan Marinescu 0:a792d4bf36c2 180 // The equeue_cancel function is irq safe.
Bogdan Marinescu 0:a792d4bf36c2 181 //
Bogdan Marinescu 0:a792d4bf36c2 182 // If called while the event queue's dispatch loop is active, equeue_cancel
Bogdan Marinescu 0:a792d4bf36c2 183 // does not guarantee that the event will not not execute after it returns as
Bogdan Marinescu 0:a792d4bf36c2 184 // the event may have already begun executing.
Bogdan Marinescu 0:a792d4bf36c2 185 void equeue_cancel(equeue_t *queue, int id);
Bogdan Marinescu 0:a792d4bf36c2 186
Bogdan Marinescu 0:a792d4bf36c2 187 // Background an event queue onto a single-shot timer
Bogdan Marinescu 0:a792d4bf36c2 188 //
Bogdan Marinescu 0:a792d4bf36c2 189 // The provided update function will be called to indicate when the queue
Bogdan Marinescu 0:a792d4bf36c2 190 // should be dispatched. A negative timeout will be passed to the update
Bogdan Marinescu 0:a792d4bf36c2 191 // function when the timer is no longer needed.
Bogdan Marinescu 0:a792d4bf36c2 192 //
Bogdan Marinescu 0:a792d4bf36c2 193 // Passing a null update function disables the existing timer.
Bogdan Marinescu 0:a792d4bf36c2 194 //
Bogdan Marinescu 0:a792d4bf36c2 195 // The equeue_background function allows an event queue to take advantage
Bogdan Marinescu 0:a792d4bf36c2 196 // of hardware timers or even other event loops, allowing an event queue to
Bogdan Marinescu 0:a792d4bf36c2 197 // be effectively backgrounded.
Bogdan Marinescu 0:a792d4bf36c2 198 void equeue_background(equeue_t *queue,
Bogdan Marinescu 0:a792d4bf36c2 199 void (*update)(void *timer, int ms), void *timer);
Bogdan Marinescu 0:a792d4bf36c2 200
Bogdan Marinescu 0:a792d4bf36c2 201 // Chain an event queue onto another event queue
Bogdan Marinescu 0:a792d4bf36c2 202 //
Bogdan Marinescu 0:a792d4bf36c2 203 // After chaining a queue to a target, calling equeue_dispatch on the
Bogdan Marinescu 0:a792d4bf36c2 204 // target queue will also dispatch events from this queue. The queues
Bogdan Marinescu 0:a792d4bf36c2 205 // use their own buffers and events must be managed independently.
Bogdan Marinescu 0:a792d4bf36c2 206 //
Bogdan Marinescu 0:a792d4bf36c2 207 // Passing a null queue as the target will unchain the existing queue.
Bogdan Marinescu 0:a792d4bf36c2 208 //
Bogdan Marinescu 0:a792d4bf36c2 209 // The equeue_chain function allows multiple equeues to be composed, sharing
Bogdan Marinescu 0:a792d4bf36c2 210 // the context of a dispatch loop while still being managed independently.
Bogdan Marinescu 0:a792d4bf36c2 211 void equeue_chain(equeue_t *queue, equeue_t *target);
Bogdan Marinescu 0:a792d4bf36c2 212
Bogdan Marinescu 0:a792d4bf36c2 213
Bogdan Marinescu 0:a792d4bf36c2 214 #ifdef __cplusplus
Bogdan Marinescu 0:a792d4bf36c2 215 }
Bogdan Marinescu 0:a792d4bf36c2 216 #endif
Bogdan Marinescu 0:a792d4bf36c2 217
Bogdan Marinescu 0:a792d4bf36c2 218 #endif