The open imaging DSP library
Loading...
Searching...
No Matches
ring.h
1
5#ifndef MPIX_RING_H
6#define MPIX_RING_H
7
8#include <assert.h>
9#include <errno.h>
10#include <stdbool.h>
11#include <string.h>
12
13#include <mpix/port.h>
14#include <mpix/types.h>
15#include <mpix/utils.h>
16
17static inline void mpix_ring_free(struct mpix_ring *ring)
18{
19 if (ring->allocated) {
20 ring->allocated = false;
22 }
23}
24
25static inline int mpix_ring_alloc(struct mpix_ring *ring)
26{
27 /* If no buffer is provided, allocate one */
28 if (ring->buffer == NULL) {
29 ring->buffer = mpix_port_alloc(ring->size);
30 if (ring->buffer == NULL) {
31 return -ENOMEM;
32 }
33
34 ring->allocated = true;
35 }
36
37 return 0;
38}
39
40static inline bool mpix_ring_is_full(struct mpix_ring *ring)
41{
42 return ring->full;
43}
44
45static inline bool mpix_ring_is_empty(struct mpix_ring *ring)
46{
47 return ring->head == ring->tail && !ring->full;
48}
49
50static inline size_t mpix_ring_free_size(struct mpix_ring *ring)
51{
52 if (ring->head < ring->tail) {
53 /* [::::H T::::]
54 * ^^^^^^^
55 */
56 return ring->tail - ring->head;
57 }
58 if (ring->tail < ring->head) {
59 /* [ T::::::H ]
60 * ^^^^^
61 */
62 return ring->size - ring->head;
63 }
64 if (mpix_ring_is_empty(ring)) {
65 /* [ TH ]
66 * ^^^^^
67 */
68 return ring->size - ring->head;
69 } else {
70 /* [::::::::::HT::::]
71 */
72 return 0;
73 }
74}
75
76static inline size_t mpix_ring_used_size(struct mpix_ring *ring)
77{
78 if (ring->head < ring->tail) {
79 /* [::::H T::::]
80 * ^^^^^
81 */
82 return ring->size - ring->tail;
83 }
84 if (ring->tail < ring->head) {
85 /* [ T::::::H ]
86 * ^^^^^^^
87 */
88 return ring->head - ring->tail;
89 }
90 if (mpix_ring_is_full(ring)) {
91 /* [::::::::::HT::::]
92 * ^^^^^
93 */
94 assert(ring->head == ring->tail);
95 return ring->size - ring->tail;
96 } else {
97 /* [ TH ]
98 */
99 assert(ring->head == ring->tail);
100 return 0;
101 }
102}
103
104static inline size_t mpix_ring_peek_size(struct mpix_ring *ring)
105{
106 if (ring->head < ring->tail && ring->tail <= ring->peek) {
107 /* [::::H T:P::]
108 * ^^^
109 */
110 return ring->size - ring->peek;
111 }
112 if (ring->peek < ring->head && ring->head < ring->tail) {
113 /* [:P::H T::::]
114 * ^^^
115 */
116 return ring->head - ring->peek;
117 }
118 if (ring->tail <= ring->peek && ring->peek < ring->head) {
119 /* [ T:P::::H ]
120 * ^^^^^
121 */
122 return ring->head - ring->peek;
123 }
124 if (mpix_ring_is_full(ring) && ring->tail <= ring->peek) {
125 /* [::::::::::HT:P::]
126 * ^^^
127 */
128 assert(ring->head == ring->tail);
129 return ring->size - ring->peek;
130 }
131 if (mpix_ring_is_full(ring) && ring->peek <= ring->head) {
132 /* [::P:::::::HT::::]
133 * ^^^^^^^^
134 */
135 assert(ring->head == ring->tail);
136 return ring->head - ring->peek;
137 }
138 return 0;
139}
140
141static inline size_t mpix_ring_total_used(struct mpix_ring *ring)
142{
143 if (ring->head < ring->tail) {
144 /* [::::H T::::]
145 * ^^^^^ ^^^^^
146 */
147 return ring->head + ring->size - ring->tail;
148 }
149 if (ring->tail < ring->head) {
150 /* [ T::::::H ]
151 * ^^^^^^^^
152 */
153 return ring->head - ring->tail;
154 }
155 if (mpix_ring_is_full(ring)) {
156 /* [::::::::::HT::::]
157 * ^^^^^^^^^^^^^^^^
158 */
159 assert(ring->head == ring->tail);
160 return ring->size;
161 } else {
162 /* [ TH ]
163 */
164 assert(ring->head == ring->tail);
165 return 0;
166 }
167}
168
169static inline size_t mpix_ring_total_free(struct mpix_ring *ring)
170{
171 return ring->size - mpix_ring_total_used(ring);
172}
173
174static inline void mpix_ring_reset_peek(struct mpix_ring *ring)
175{
176 ring->peek = ring->tail;
177}
178
179static inline uint8_t *mpix_ring_write(struct mpix_ring *ring, size_t size)
180{
181 uint8_t *buffer = ring->buffer + ring->head;
182
183 if (mpix_ring_free_size(ring) < size) {
184 MPIX_DBG("Not enough room (%zu) for %zu bytes", mpix_ring_free_size(ring), size);
185 return NULL;
186 }
187 ring->head = (ring->head + size) % ring->size;
188 ring->full = (ring->head == ring->tail);
189 mpix_ring_reset_peek(ring);
190 return buffer;
191}
192
193static inline uint8_t *mpix_ring_read(struct mpix_ring *ring, size_t size)
194{
195 uint8_t *buffer = ring->buffer + ring->tail;
196
197 if (mpix_ring_used_size(ring) < size) {
198 return NULL;
199 }
200 ring->tail = (ring->tail + size) % ring->size;
201 ring->full = false;
202 mpix_ring_reset_peek(ring);
203
204 /* To avoid fragmentation, re-align the buffer if empty */
205 if (mpix_ring_used_size(ring) == 0) {
206 ring->tail = ring->head = ring->peek = 0;
207 }
208
209 return buffer;
210}
211
212static inline uint8_t *mpix_ring_peek(struct mpix_ring *ring, size_t size)
213{
214 uint8_t *buffer = ring->buffer + ring->peek;
215
216 if (mpix_ring_peek_size(ring) < size) {
217 return NULL;
218 }
219 ring->peek = (ring->peek + size) % ring->size;
220 return buffer;
221}
222
223#endif
void mpix_port_free(void *mem)
Free a buffer allocated with mpix_port_alloc().
void * mpix_port_alloc(size_t size)
Allocate a buffer to use with libmpix.
Ring buffer of pixels.
Definition types.h:86
uint8_t allocated
Definition types.h:100
size_t peek
Definition types.h:96
uint8_t * buffer
Definition types.h:88
size_t head
Definition types.h:92
uint8_t full
Definition types.h:98
size_t size
Definition types.h:90
size_t tail
Definition types.h:94