utils
utilities in C for microcontrollers
queue.h
Go to the documentation of this file.
1 
6 #ifndef QUEUE_H
7 #define QUEUE_H
8 
9 #include <stdlib.h>
10 #include <stdint.h>
11 
12 /*
13 A very simple circular buffer.
14 
15 Example:
16 QUEUE(test, int, count)
17 
18 Creates:
19 struct queue_test {...};
20 static inline void queue_test_init(struct queue_test *) {...}
21 static inline int queue_test_push(struct queue_test *, int *) {...}
22 static inline int queue_test_pop(struct queue_test *, int *) {...}
23 
24 API:
25 queue_*_init initializes a queue
26 queue_*_push pushes an item onto the queue, returns 0 if successful, not 0 if fail
27 queue_*_pop pops an item from the queue, returns 0 if successful, not 0 if fail
28 queue_*_foreach takes a function pointer and pointer to some context and for each
29  element in the queue calls the function with a pointer to that element. If the
30  returns zero queue_*_foreach will continue processing the rest of the items, if
31  the function returns non zero then queue_*_foreach will not process any more items.
32 
33 */
34 
41 #define QUEUE(name, type, size) \
42 struct queue_##name { \
43  type storage[size]; \
44  /*index of the read head, initialy 0*/ \
45  size_t read; \
46  /*index of the write head, initialy 0*/ \
47  size_t write; \
48  /*number of items in the queue*/ \
49  size_t count; \
50 }; \
51 static inline int queue_##name##_init(volatile struct queue_##name *self) { \
52  if (!self) return -1; \
53  self->read = 0; \
54  self->write = 0; \
55  self->count = 0; \
56  return 0; \
57 } \
58 static inline int queue_##name##_push(volatile struct queue_##name *self, \
59  const volatile type *item) { \
60  if (!self || !item) return -1; \
61  if (self->count < size) { \
62  size_t next = (self->write + 1) % size; \
63  self->storage[next] = *item; \
64  self->write = next; \
65  self->count++; \
66  return 0; \
67  } else { \
68  return -1; \
69  } \
70 } \
71 static inline int queue_##name##_pop(volatile struct queue_##name *self, \
72  volatile type *item) { \
73  if (!self || !item) return -1; \
74  if (self->count > 0) { \
75  size_t next = (self->read + 1) % size; \
76  *item = self->storage[next]; \
77  self->read = next; \
78  self->count--; \
79  return 0; \
80  } else { \
81  return -1; \
82  } \
83 } \
84 static inline size_t queue_##name##_count(const volatile struct queue_##name *self) { \
85  if (!self) return 0; \
86  return self->count; \
87 } \
88 static inline void queue_##name##_foreach(volatile struct queue_##name *self, \
89  int (*fun)(volatile type *, volatile void *), \
90  volatile void *ctx) { \
91  if (!self) return; \
92  if (fun == NULL) return; \
93  for (size_t i = 0; i < self->count; ++i) { \
94  if (fun(&self->storage[(self->read + i + 1) % size], ctx) != 0) break; \
95  } \
96 }
97 
98 #ifdef DOXYGEN
99 QUEUE(NAME, TYPE, SIZE);
146 #endif
147 
148 
149 #endif //QUEUE_H
150 
#define QUEUE(name, type, size)
Generates the queue api.
Definition: queue.h:41