Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
equeue.h
00001 00002 /** \addtogroup events */ 00003 /** @{*/ 00004 /* 00005 * Flexible event queue for dispatching events 00006 * 00007 * Copyright (c) 2016 Christopher Haster 00008 * 00009 * Licensed under the Apache License, Version 2.0 (the "License"); 00010 * you may not use this file except in compliance with the License. 00011 * You may obtain a copy of the License at 00012 * 00013 * http://www.apache.org/licenses/LICENSE-2.0 00014 * 00015 * Unless required by applicable law or agreed to in writing, software 00016 * distributed under the License is distributed on an "AS IS" BASIS, 00017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00018 * See the License for the specific language governing permissions and 00019 * limitations under the License. 00020 */ 00021 #ifndef EQUEUE_H 00022 #define EQUEUE_H 00023 00024 #ifdef __cplusplus 00025 extern "C" { 00026 #endif 00027 00028 // Platform specific files 00029 #include "equeue/equeue_platform.h" 00030 00031 #include <stddef.h> 00032 #include <stdint.h> 00033 00034 00035 // The minimum size of an event 00036 // This size is guaranteed to fit events created by event_call 00037 #define EQUEUE_EVENT_SIZE (sizeof(struct equeue_event) + 2*sizeof(void*)) 00038 00039 // Internal event structure 00040 struct equeue_event { 00041 unsigned size; 00042 uint8_t id; 00043 uint8_t generation; 00044 00045 struct equeue_event *next; 00046 struct equeue_event *sibling; 00047 struct equeue_event **ref; 00048 00049 unsigned target; 00050 int period; 00051 void (*dtor)(void *); 00052 00053 void (*cb)(void *); 00054 // data follows 00055 }; 00056 00057 // Event queue structure 00058 typedef struct equeue { 00059 struct equeue_event *queue; 00060 unsigned tick; 00061 bool break_requested; 00062 uint8_t generation; 00063 00064 unsigned char *buffer; 00065 unsigned npw2; 00066 void *allocated; 00067 00068 struct equeue_event *chunks; 00069 struct equeue_slab { 00070 size_t size; 00071 unsigned char *data; 00072 } slab; 00073 00074 struct equeue_background { 00075 bool active; 00076 void (*update)(void *timer, int ms); 00077 void *timer; 00078 } background; 00079 00080 equeue_sema_t eventsema; 00081 equeue_mutex_t queuelock; 00082 equeue_mutex_t memlock; 00083 } equeue_t; 00084 00085 00086 // Queue lifetime operations 00087 // 00088 // Creates and destroys an event queue. The event queue either allocates a 00089 // buffer of the specified size with malloc or uses a user provided buffer 00090 // if constructed with equeue_create_inplace. 00091 // 00092 // If the event queue creation fails, equeue_create returns a negative, 00093 // platform-specific error code. 00094 int equeue_create(equeue_t *queue, size_t size); 00095 int equeue_create_inplace(equeue_t *queue, size_t size, void *buffer); 00096 void equeue_destroy(equeue_t *queue); 00097 00098 // Dispatch events 00099 // 00100 // Executes events until the specified milliseconds have passed. If ms is 00101 // negative, equeue_dispatch will dispatch events indefinitely or until 00102 // equeue_break is called on this queue. 00103 // 00104 // When called with a finite timeout, the equeue_dispatch function is 00105 // guaranteed to terminate. When called with a timeout of 0, the 00106 // equeue_dispatch does not wait and is irq safe. 00107 void equeue_dispatch(equeue_t *queue, int ms); 00108 00109 // Break out of a running event loop 00110 // 00111 // Forces the specified event queue's dispatch loop to terminate. Pending 00112 // events may finish executing, but no new events will be executed. 00113 void equeue_break(equeue_t *queue); 00114 00115 // Simple event calls 00116 // 00117 // The specified callback will be executed in the context of the event queue's 00118 // dispatch loop. When the callback is executed depends on the call function. 00119 // 00120 // equeue_call - Immediately post an event to the queue 00121 // equeue_call_in - Post an event after a specified time in milliseconds 00122 // equeue_call_every - Post an event periodically every milliseconds 00123 // 00124 // All equeue_call functions are irq safe and can act as a mechanism for 00125 // moving events out of irq contexts. 00126 // 00127 // The return value is a unique id that represents the posted event and can 00128 // be passed to equeue_cancel. If there is not enough memory to allocate the 00129 // event, equeue_call returns an id of 0. 00130 int equeue_call(equeue_t *queue, void (*cb)(void *), void *data); 00131 int equeue_call_in(equeue_t *queue, int ms, void (*cb)(void *), void *data); 00132 int equeue_call_every(equeue_t *queue, int ms, void (*cb)(void *), void *data); 00133 00134 // Allocate memory for events 00135 // 00136 // The equeue_alloc function allocates an event that can be manually dispatched 00137 // with equeue_post. The equeue_dealloc function may be used to free an event 00138 // that has not been posted. Once posted, an event's memory is managed by the 00139 // event queue and should not be deallocated. 00140 // 00141 // Both equeue_alloc and equeue_dealloc are irq safe. 00142 // 00143 // The equeue allocator is designed to minimize jitter in interrupt contexts as 00144 // well as avoid memory fragmentation on small devices. The allocator achieves 00145 // both constant-runtime and zero-fragmentation for fixed-size events, however 00146 // grows linearly as the quantity of different sized allocations increases. 00147 // 00148 // The equeue_alloc function returns a pointer to the event's allocated memory 00149 // and acts as a handle to the underlying event. If there is not enough memory 00150 // to allocate the event, equeue_alloc returns null. 00151 void *equeue_alloc(equeue_t *queue, size_t size); 00152 void equeue_dealloc(equeue_t *queue, void *event); 00153 00154 // Configure an allocated event 00155 // 00156 // equeue_event_delay - Millisecond delay before dispatching an event 00157 // equeue_event_period - Millisecond period for repeating dispatching an event 00158 // equeue_event_dtor - Destructor to run when the event is deallocated 00159 void equeue_event_delay(void *event, int ms); 00160 void equeue_event_period(void *event, int ms); 00161 void equeue_event_dtor(void *event, void (*dtor)(void *)); 00162 00163 // Post an event onto the event queue 00164 // 00165 // The equeue_post function takes a callback and a pointer to an event 00166 // allocated by equeue_alloc. The specified callback will be executed in the 00167 // context of the event queue's dispatch loop with the allocated event 00168 // as its argument. 00169 // 00170 // The equeue_post function is irq safe and can act as a mechanism for 00171 // moving events out of irq contexts. 00172 // 00173 // The return value is a unique id that represents the posted event and can 00174 // be passed to equeue_cancel. 00175 int equeue_post(equeue_t *queue, void (*cb)(void *), void *event); 00176 00177 // Cancel an in-flight event 00178 // 00179 // Attempts to cancel an event referenced by the unique id returned from 00180 // equeue_call or equeue_post. It is safe to call equeue_cancel after an event 00181 // has already been dispatched. 00182 // 00183 // The equeue_cancel function is irq safe. 00184 // 00185 // If called while the event queue's dispatch loop is active, equeue_cancel 00186 // does not guarantee that the event will not not execute after it returns as 00187 // the event may have already begun executing. 00188 void equeue_cancel(equeue_t *queue, int id); 00189 00190 // Query how much time is left for delayed event 00191 // 00192 // If event is delayed, this function can be used to query how much time 00193 // is left until the event is due to be dispatched. 00194 // 00195 // This function is irq safe. 00196 // 00197 int equeue_timeleft(equeue_t *q, int id); 00198 00199 // Background an event queue onto a single-shot timer 00200 // 00201 // The provided update function will be called to indicate when the queue 00202 // should be dispatched. A negative timeout will be passed to the update 00203 // function when the timer is no longer needed. 00204 // 00205 // Passing a null update function disables the existing timer. 00206 // 00207 // The equeue_background function allows an event queue to take advantage 00208 // of hardware timers or even other event loops, allowing an event queue to 00209 // be effectively backgrounded. 00210 void equeue_background(equeue_t *queue, 00211 void (*update)(void *timer, int ms), void *timer); 00212 00213 // Chain an event queue onto another event queue 00214 // 00215 // After chaining a queue to a target, calling equeue_dispatch on the 00216 // target queue will also dispatch events from this queue. The queues 00217 // use their own buffers and events must be managed independently. 00218 // 00219 // Passing a null queue as the target will unchain the existing queue. 00220 // 00221 // The equeue_chain function allows multiple equeues to be composed, sharing 00222 // the context of a dispatch loop while still being managed independently. 00223 void equeue_chain(equeue_t *queue, equeue_t *target); 00224 00225 00226 #ifdef __cplusplus 00227 } 00228 #endif 00229 00230 #endif 00231 00232 /** @}*/
Generated on Tue Jul 12 2022 12:43:55 by
