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