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

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.