tsrb.h
3.81 KB
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 */
/** @} */