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