Lely core libraries  2.2.5
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 
47 struct 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
67 
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
93 extern "C" {
94 #endif
95 
108 int can_buf_init(struct can_buf *buf, size_t size);
109 
111 void can_buf_fini(struct can_buf *buf);
112 
124 struct can_buf *can_buf_create(size_t size);
125 
126 // Finalizes and frees a CAN frame buffer. @see can_buf_create(), can_buf_fini()
127 void can_buf_destroy(struct can_buf *buf);
128 
130 LELY_CAN_BUF_INLINE void can_buf_clear(struct can_buf *buf);
131 
137 LELY_CAN_BUF_INLINE size_t can_buf_size(const struct can_buf *buf);
138 
144 LELY_CAN_BUF_INLINE size_t can_buf_capacity(const struct can_buf *buf);
145 
154 size_t can_buf_reserve(struct can_buf *buf, size_t n);
155 
167 LELY_CAN_BUF_INLINE size_t can_buf_peek(
168  struct can_buf *buf, struct can_msg *ptr, size_t n);
169 
181 LELY_CAN_BUF_INLINE size_t can_buf_read(
182  struct can_buf *buf, struct can_msg *ptr, size_t n);
183 
195 LELY_CAN_BUF_INLINE size_t can_buf_write(
196  struct can_buf *buf, const struct can_msg *ptr, size_t n);
197 
198 inline void
199 can_buf_clear(struct can_buf *buf)
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);
205  atomic_store_explicit(&buf->end, begin, memory_order_release);
206 #endif
207 }
208 
209 inline size_t
210 can_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 
225 inline size_t
226 can_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 
241 inline size_t
242 can_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(
254  &buf->end, memory_order_acquire);
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 
267 inline size_t
268 can_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(
280  &buf->end, memory_order_acquire);
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
292  atomic_store_explicit(&buf->begin, begin, memory_order_release);
293 #endif
294  }
295 
296  return n;
297 }
298 
299 inline size_t
300 can_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(
312  &buf->begin, memory_order_acquire);
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
322  atomic_store_explicit(&buf->end, end, memory_order_release);
323 #endif
324  }
325 
326  return n;
327 }
328 
329 #ifdef __cplusplus
330 }
331 #endif
332 
333 #endif // !LELY_CAN_BUF_H_
can_buf_peek
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
can_buf
A CAN frame buffer.
Definition: buf.h:47
can_buf_clear
void can_buf_clear(struct can_buf *buf)
Clears a CAN frame buffer.
Definition: buf.h:199
can_buf_reserve
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
can_buf::size
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
can_msg
A CAN or CAN FD format frame.
Definition: msg.h:87
can_buf::ptr
struct can_msg * ptr
A pointer to the allocated memory for the buffer.
Definition: buf.h:49
can_buf_create
struct can_buf * can_buf_create(size_t size)
Allocates and initializes a CAN frame buffer.
Definition: buf.c:75
can_buf_capacity
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
can_buf_write
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
can_buf::begin
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
stdatomic.h
can_buf_read
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
msg.h
can_buf::end
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
can_buf_fini
void can_buf_fini(struct can_buf *buf)
Finalizes a CAN frame buffer.
Definition: buf.c:67
can_buf_init
int can_buf_init(struct can_buf *buf, size_t size)
Initializes a CAN frame buffer.
Definition: buf.c:39
can_buf_size
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