Lely core libraries 1.9.2
buf.h
Go to the documentation of this file.
1
28#ifndef LELY_CAN_BUF_H_
29#define LELY_CAN_BUF_H_
30
31#ifndef LELY_NO_ATOMICS
32#define LELY_NO_ATOMICS 1
33#ifndef LELY_NO_THREADS
34#include <lely/libc/stdatomic.h>
35#ifndef __STDC_NO_ATOMICS__
36#undef LELY_NO_ATOMICS
37#endif
38#endif
39#endif
40#include <lely/can/msg.h>
41
42#ifndef LELY_CAN_BUF_INLINE
43#define LELY_CAN_BUF_INLINE static inline
44#endif
45
47struct can_buf {
49 struct can_msg *ptr;
56 size_t size;
62#ifdef LELY_NO_ATOMICS
63 size_t begin;
64#else
65 atomic_size_t begin;
66#endif
72#ifdef LELY_NO_ATOMICS
73 size_t end;
74#else
75 atomic_size_t end;
76#endif
77};
78
80#ifdef LELY_NO_ATOMICS
81#define CAN_BUF_INIT \
82 { \
83 NULL, 0, 0, 0 \
84 }
85#else
86#define CAN_BUF_INIT \
87 { \
88 NULL, 0, ATOMIC_VAR_INIT(0), ATOMIC_VAR_INIT(0) \
89 }
90#endif
91
92#ifdef __cplusplus
93extern "C" {
94#endif
95
108int can_buf_init(struct can_buf *buf, size_t size);
109
111void can_buf_fini(struct can_buf *buf);
112
124struct can_buf *can_buf_create(size_t size);
125
126// Finalizes and frees a CAN frame buffer. @see can_buf_create(), can_buf_fini()
127void can_buf_destroy(struct can_buf *buf);
128
130LELY_CAN_BUF_INLINE void can_buf_clear(struct can_buf *buf);
131
137LELY_CAN_BUF_INLINE size_t can_buf_size(const struct can_buf *buf);
138
144LELY_CAN_BUF_INLINE size_t can_buf_capacity(const struct can_buf *buf);
145
154size_t can_buf_reserve(struct can_buf *buf, size_t n);
155
167LELY_CAN_BUF_INLINE size_t can_buf_peek(
168 struct can_buf *buf, struct can_msg *ptr, size_t n);
169
181LELY_CAN_BUF_INLINE size_t can_buf_read(
182 struct can_buf *buf, struct can_msg *ptr, size_t n);
183
195LELY_CAN_BUF_INLINE size_t can_buf_write(
196 struct can_buf *buf, const struct can_msg *ptr, size_t n);
197
198inline void
200{
201#ifdef LELY_NO_ATOMICS
202 buf->end = buf->begin;
203#else
204 size_t begin = atomic_load_explicit(&buf->begin, memory_order_acquire);
206#endif
207}
208
209inline size_t
210can_buf_size(const struct can_buf *buf)
211{
212#ifdef LELY_NO_ATOMICS
213 size_t begin = buf->begin;
214 size_t end = buf->end;
215#else
216 size_t begin = atomic_load_explicit(
217 &((struct can_buf *)buf)->begin, memory_order_acquire);
218 size_t end = atomic_load_explicit(
219 &((struct can_buf *)buf)->end, memory_order_acquire);
220#endif
221
222 return (end - begin) & buf->size;
223}
224
225inline size_t
226can_buf_capacity(const struct can_buf *buf)
227{
228#ifdef LELY_NO_ATOMICS
229 size_t begin = buf->begin;
230 size_t end = buf->end;
231#else
232 size_t begin = atomic_load_explicit(
233 &((struct can_buf *)buf)->begin, memory_order_acquire);
234 size_t end = atomic_load_explicit(
235 &((struct can_buf *)buf)->end, memory_order_acquire);
236#endif
237
238 return (begin - end - 1) & buf->size;
239}
240
241inline size_t
242can_buf_peek(struct can_buf *buf, struct can_msg *ptr, size_t n)
243{
244#ifdef LELY_NO_ATOMICS
245 size_t begin = buf->begin;
246#else
247 size_t begin = atomic_load_explicit(&buf->begin, memory_order_acquire);
248#endif
249 for (size_t i = 0; i < n; i++) {
250#ifdef LELY_NO_ATOMICS
251 size_t end = buf->end;
252#else
253 size_t end = atomic_load_explicit(
255#endif
256 if (!((end - begin) & buf->size))
257 return i;
258
259 if (ptr)
260 ptr[i] = buf->ptr[begin & buf->size];
261 begin++;
262 }
263
264 return n;
265}
266
267inline size_t
268can_buf_read(struct can_buf *buf, struct can_msg *ptr, size_t n)
269{
270#ifdef LELY_NO_ATOMICS
271 size_t begin = buf->begin;
272#else
273 size_t begin = atomic_load_explicit(&buf->begin, memory_order_acquire);
274#endif
275 for (size_t i = 0; i < n; i++) {
276#ifdef LELY_NO_ATOMICS
277 size_t end = buf->end;
278#else
279 size_t end = atomic_load_explicit(
281#endif
282 if (!((end - begin) & buf->size))
283 return i;
284
285 if (ptr)
286 ptr[i] = buf->ptr[begin & buf->size];
287 begin++;
288
289#ifdef LELY_NO_ATOMICS
290 buf->begin = begin;
291#else
293#endif
294 }
295
296 return n;
297}
298
299inline size_t
300can_buf_write(struct can_buf *buf, const struct can_msg *ptr, size_t n)
301{
302#ifdef LELY_NO_ATOMICS
303 size_t end = buf->end;
304#else
305 size_t end = atomic_load_explicit(&buf->end, memory_order_acquire);
306#endif
307 for (size_t i = 0; i < n; i++) {
308#ifdef LELY_NO_ATOMICS
309 size_t begin = buf->begin;
310#else
311 size_t begin = atomic_load_explicit(
313#endif
314 if (!((begin - end - 1) & buf->size))
315 return i;
316
317 buf->ptr[end++ & buf->size] = ptr[i];
318
319#ifdef LELY_NO_ATOMICS
320 buf->end = end;
321#else
323#endif
324 }
325
326 return n;
327}
328
329#ifdef __cplusplus
330}
331#endif
332
333#endif // !LELY_CAN_BUF_H_
void can_buf_clear(struct can_buf *buf)
Clears a CAN frame buffer.
Definition: buf.h:199
struct can_buf * can_buf_create(size_t size)
Allocates and initializes a CAN frame buffer.
Definition: buf.c:75
size_t can_buf_size(const struct can_buf *buf)
Returns the number of frames available for reading in a CAN buffer.
Definition: buf.h:210
size_t can_buf_capacity(const struct can_buf *buf)
Returns the number of frames available for writing in a CAN buffer.
Definition: buf.h:226
size_t can_buf_reserve(struct can_buf *buf, size_t n)
Resizes a CAN frame buffer, if necessary, to make room for at least n additional frames.
Definition: buf.c:111
size_t can_buf_read(struct can_buf *buf, struct can_msg *ptr, size_t n)
Reads, and removes, frames from a CAN frame buffer.
Definition: buf.h:268
int can_buf_init(struct can_buf *buf, size_t size)
Initializes a CAN frame buffer.
Definition: buf.c:39
size_t can_buf_peek(struct can_buf *buf, struct can_msg *ptr, size_t n)
Reads, but does not remove, frames from a CAN frame buffer.
Definition: buf.h:242
void can_buf_fini(struct can_buf *buf)
Finalizes a CAN frame buffer.
Definition: buf.c:67
size_t can_buf_write(struct can_buf *buf, const struct can_msg *ptr, size_t n)
Writes frames to a CAN frame buffer.
Definition: buf.h:300
This header file is part of the CAN library; it contains the CAN frame declarations.
This header file is part of the C11 and POSIX compatibility library; it includes <stdatomic....
@ memory_order_release
A store operation performs a release operation on the affected memory location.
Definition: stdatomic.h:160
@ memory_order_acquire
A load operation performs an acquire operation on the affected memory location.
Definition: stdatomic.h:151
#define atomic_store_explicit(object, desired, order)
Atomically replaces the value at object with the value of desired.
Definition: stdatomic.h:327
A CAN frame buffer.
Definition: buf.h:47
struct can_msg * ptr
A pointer to the allocated memory for the buffer.
Definition: buf.h:49
size_t end
The offset (with respect to ptr) of one past the last value available for reading (and the first avai...
Definition: buf.h:73
size_t begin
The offset (with respect to ptr) of the first value available for reading (and two past the last avai...
Definition: buf.h:63
size_t size
The total size (in number of frames) of the buffer, excluding the unused frame used to distinguish be...
Definition: buf.h:56
A CAN or CAN FD format frame.
Definition: msg.h:88