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