Blame view

RIOT/core/include/cib.h 4.26 KB
fb11e647   vrobic   reseau statique a...
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
  /*
   * Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.de>
   *               2013 Freie Universitรคt Berlin
   *
   * 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.
   */
  
   /**
   * @addtogroup  core_util
   * @{
   *
   * @file
   * @brief       Circular integer buffer interface
   * @details     This structure provides an organizational interface
   *              and combined with an memory array forms a circular buffer.
   *
   * @author      Kaspar Schleiser <kaspar@schleiser.de>
   */
  
  #ifndef CIB_H
  #define CIB_H
  
  #include "assert.h"
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /**
   * @brief circular integer buffer structure
   */
  typedef struct {
      unsigned int read_count;    /**< number of (successful) read accesses */
      unsigned int write_count;   /**< number of (successful) write accesses */
      unsigned int mask;          /**< Size of buffer -1, i.e. mask of the bits */
  } cib_t;
  
  /**
   * @brief   Initialize cib_t to a given size.
   */
  #define CIB_INIT(SIZE) { 0, 0, (SIZE) - 1 }
  
  /**
   * @brief Initialize @p cib to 0 and set buffer size to @p size.
   *
   * @param[out] cib      Buffer to initialize.
   *                      Must not be NULL.
   * @param[in]  size     Size of the buffer, must not exceed MAXINT/2.
   *                      Should be equal to 0 or power of 2.
   */
  static inline void cib_init(cib_t *__restrict cib, unsigned int size)
  {
      /* check if size is a power of 2 by comparing it to its complement */
      assert(!(size & (size - 1)));
  
      cib_t c = CIB_INIT(size);
      *cib = c;
  }
  
  /**
   * @brief Calculates difference between cib_put() and cib_get() accesses.
   *
   * @param[in] cib       the cib_t to check.
   *                      Must not be NULL.
   * @return How often cib_get() can be called before @p cib is empty.
   */
  static inline unsigned int cib_avail(const cib_t *cib)
  {
      return cib->write_count - cib->read_count;
  }
  
  /**
   * @brief Check if cib is full.
   *
   * @param[in] cib       the cib_t to check.
   *                      Must not be NULL.
   * @return      1 if cib_put() would return "-1", 0 otherwise
   */
  static inline unsigned int cib_full(const cib_t *cib)
  {
      return ((int) cib_avail(cib)) > ((int) cib->mask);
  }
  
  /**
   * @brief Get the index of the next item in buffer.
   *
   * @param[in,out] cib   corresponding *cib* to buffer.
   *                      Must not be NULL.
   * @return index of next item, -1 if the buffer is empty
   */
  static inline int cib_get(cib_t *__restrict cib)
  {
      if (cib->write_count > cib->read_count) {
          return (int) (cib->read_count++ & cib->mask);
      }
  
      return -1;
  }
  
  /**
   * @brief Get the index of the next item in buffer without removing it.
   *
   * @param[in,out] cib   corresponding *cib* to buffer.
   *                      Must not be NULL.
   * @return index of next item, -1 if the buffer is empty
   */
  static inline int cib_peek(cib_t *__restrict cib)
  {
      if (cib->write_count > cib->read_count) {
          return (int) (cib->read_count & cib->mask);
      }
  
      return -1;
  }
  
  /**
   * @brief Get the index of the next item in buffer.
   *
   * Unsafe version, *must not* be called if buffer is empty!
   *
   * @param[in,out] cib   corresponding *cib* to buffer.
   *                      Must not be NULL.
   * @return index of next item
   */
  static inline int cib_get_unsafe(cib_t *cib)
  {
          return (int) (cib->read_count++ & cib->mask);
  }
  
  /**
   * @brief Get index for item in buffer to put to.
   *
   * @param[in,out] cib   corresponding *cib* to buffer.
   *                      Must not be NULL.
   * @return index of item to put to, -1 if the buffer is full
   */
  static inline int cib_put(cib_t *__restrict cib)
  {
      unsigned int avail = cib_avail(cib);
  
      /* We use a signed compare, because the mask is -1u for an empty CIB. */
      if ((int) avail <= (int) cib->mask) {
          return (int) (cib->write_count++ & cib->mask);
      }
  
      return -1;
  }
  
  /**
   * @brief Get index for item in buffer to put to.
   *
   * Unsafe version, *must not* be called if buffer is full!
   *
   * @param[in,out] cib   corresponding *cib* to buffer.
   *                      Must not be NULL.
   * @return index of item to put to
   */
  static inline int cib_put_unsafe(cib_t *cib)
  {
      return (int) (cib->write_count++ & cib->mask);
  }
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif /* CIB_H */
  /** @} */