Blame view

RIOT/sys/include/tsrb.h 3.81 KB
a752c7ab   elopes   add first test an...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
  /*
   * Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
   *
   * This file is subject to the terms and conditions of the GNU Lesser
   * General Public License v2.1. See the file LICENSE in the top level
   * directory for more details.
   */
  
  /**
   * @defgroup    sys_tsrb Thread safe ringbuffer
   * @ingroup     sys
   * @brief       Thread-safe ringbuffer implementation
   * @{
   *
   * @file
   * @brief       Thread-safe ringbuffer interface definition
   *
   * @note        This ringbuffer implementation can be used without locking if
   *              there's only one producer and one consumer.
   *
   * @attention   Buffer size must be a power of two!
   *
   * @author      Kaspar Schleiser <kaspar@schleiser.de>
   */
  
  #ifndef TSRB_H
  #define TSRB_H
  
  #include <assert.h>
  #include <stddef.h>
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /**
   * @brief     thread-safe ringbuffer struct
   */
  typedef struct tsrb {
      char *buf;                  /**< Buffer to operate on. */
      unsigned int size;          /**< Size of buf. */
      volatile unsigned reads;    /**< total number of reads */
      volatile unsigned writes;   /**< total number of writes */
  } tsrb_t;
  
  /**
   * @brief Static initializer
   */
  #define TSRB_INIT(BUF) { (BUF), sizeof (BUF), 0, 0 }
  
  /**
   * @brief        Initialize a tsrb.
   * @param[out]   rb        Datum to initialize.
   * @param[in]    buffer    Buffer to use by tsrb.
   * @param[in]    bufsize   `sizeof (buffer)`
   */
  static inline void tsrb_init(tsrb_t *rb, char *buffer, unsigned bufsize)
  {
      /* make sure bufsize is a power of two.
       * http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/
       */
      assert((bufsize != 0) && ((bufsize & (~bufsize + 1)) == bufsize));
  
      rb->buf = buffer;
      rb->size = bufsize;
      rb->reads = 0;
      rb->writes = 0;
  }
  
  /**
   * @brief       Test if the tsrb is empty.
   * @param[in]   rb  Ringbuffer to operate on
   * @return      0   if not empty
   * @return      1   otherwise
   */
  static inline int tsrb_empty(const tsrb_t *rb)
  {
      return (rb->reads == rb->writes);
  }
  
  
  /**
   * @brief       Get number of bytes available for reading
   * @param[in]   rb  Ringbuffer to operate on
   * @return      nr of available bytes
   */
  static inline unsigned int tsrb_avail(const tsrb_t *rb)
  {
      return (rb->writes - rb->reads);
  }
  
  /**
   * @brief       Test if the tsrb is full
   * @param[in]   rb  Ringbuffer to operate on
   * @return      0   if not full
   * @return      1   otherwise
   */
  static inline int tsrb_full(const tsrb_t *rb)
  {
      return (rb->writes - rb->reads) == rb->size;
  }
  
  /**
   * @brief       Get free space in ringbuffer
   * @param[in]   rb  Ringbuffer to operate on
   * @return      nr of available bytes
   */
  static inline unsigned int tsrb_free(const tsrb_t *rb)
  {
      return (rb->size - rb->writes + rb->reads);
  }
  
  /**
   * @brief       Get a byte from ringbuffer
   * @param[in]   rb  Ringbuffer to operate on
   * @return      >=0 byte that has been read
   * @return      -1  if no byte available
   */
  int tsrb_get_one(tsrb_t *rb);
  
  /**
   * @brief       Get bytes from ringbuffer
   * @param[in]   rb  Ringbuffer to operate on
   * @param[out]  dst buffer to write to
   * @param[in]   n   max number of bytes to write to @p dst
   * @return      nr of bytes written to @p dst
   */
  int tsrb_get(tsrb_t *rb, char *dst, size_t n);
  
  /**
   * @brief       Add a byte to ringbuffer
   * @param[in]   rb  Ringbuffer to operate on
   * @param[in]   c   Character to add to ringbuffer
   * @return      0   on success
   * @return      -1  if no space available
   */
  int tsrb_add_one(tsrb_t *rb, char c);
  
  /**
   * @brief       Add bytes to ringbuffer
   * @param[in]   rb  Ringbuffer to operate on
   * @param[in]   src buffer to read from
   * @param[in]   n   max number of bytes to read from @p src
   * @return      nr of bytes read from @p src
   */
  int tsrb_add(tsrb_t *rb, const char *src, size_t n);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif /* TSRB_H */
  /** @} */