librfn
An ad-hoc utility library
ringbuf.c
Go to the documentation of this file.
1 /*
2  * ringbuf.c
3  *
4  * Part of librfn (a general utility library from redfelineninja.org.uk)
5  *
6  * Copyright (C) 2014 Daniel Thompson <daniel@redfelineninja.org.uk>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published
10  * by the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  */
13 
14 #include "librfn/ringbuf.h"
15 
16 #include <assert.h>
17 #include <string.h>
18 
19 #include "librfn/atomic.h"
20 #include "librfn/util.h"
21 
22 void ringbuf_init(ringbuf_t *rb, void *bufp, size_t buf_len)
23 {
24  memset(rb, 0, sizeof(ringbuf_t));
25 
26  rb->bufp = bufp;
27  rb->buf_len = buf_len;
28 }
29 
30 /* TODO: the memory ordering in this function is needlessly aggressive */
32 {
33  unsigned int readi = atomic_load(&rb->readi);
34  int d;
35 
36  assert(readi < rb->buf_len);
37 
38  if (readi == atomic_load(&rb->writei))
39  return -1;
40 
41  d = rb->bufp[readi];
42  atomic_signal_fence(memory_order_seq_cst);
43 
44  if (++readi >= rb->buf_len)
45  readi -= rb->buf_len;
46 
47  atomic_store(&rb->readi, readi);
48  return d;
49 }
50 
51 /* TODO: the memory ordering in this function is needlessly aggressive */
53 {
54  return atomic_load(&rb->readi) == atomic_load(&rb->writei);
55 }
56 
57 /* TODO: the memory ordering in this function is needlessly aggressive */
58 bool ringbuf_put(ringbuf_t *rb, uint8_t d)
59 {
60  unsigned int writei = atomic_load(&rb->writei);
61  unsigned int old_writei = writei;
62 
63  if (++writei >= rb->buf_len)
64  writei -= rb->buf_len;
65 
66  if (writei == atomic_load(&rb->readi))
67  return false;
68 
69  rb->bufp[old_writei] = d;
70  atomic_signal_fence(memory_order_seq_cst);
71  atomic_store(&rb->writei, writei);
72  return true;
73 }
74 
75 void ringbuf_putchar(void *rb, char c)
76 {
77  while (!ringbuf_put(rb, c))
78  ;
79 }
struct charlie c
void ringbuf_putchar(void *rb, char c)
Insert a character into the ring buffer.
Definition: ringbuf.c:75
Ring buffer descriptor.
Definition: ringbuf.h:38
atomic_uint writei
Definition: ringbuf.h:42
int ringbuf_get(ringbuf_t *rb)
Extract a byte from the ring buffer.
Definition: ringbuf.c:31
atomic_uint readi
Definition: ringbuf.h:41
size_t buf_len
Definition: ringbuf.h:40
bool ringbuf_empty(ringbuf_t *rb)
Test whether the ring buffer contains any data.
Definition: ringbuf.c:52
bool ringbuf_put(ringbuf_t *rb, uint8_t d)
Insert a byte into the ring buffer.
Definition: ringbuf.c:58
uint8_t * bufp
Definition: ringbuf.h:39
void ringbuf_init(ringbuf_t *rb, void *bufp, size_t buf_len)
Runtime initializer for a ring buffer descriptor.
Definition: ringbuf.c:22