23 #ifndef _CIRCULAR_BUFFER_H_
24 #define _CIRCULAR_BUFFER_H_
35 #define DEBUG(X) do{X} while(0);
37 #define DEBUG(X) do{} while(0);
48 size_t d_bufLen_I, d_readNdx_I, d_writeNdx_I;
49 size_t d_n_avail_write_I, d_n_avail_read_I;
57 bool d_doWriteBlock, d_doFullRead, d_doAbort;
59 void delete_mutex_cond () {
76 bool doWriteBlock =
true,
bool doFullRead =
false) {
78 throw std::runtime_error (
"circular_buffer(): "
79 "Number of items to buffer must be > 0.\n");
80 d_bufLen_I = bufLen_I;
81 d_buffer = (T*)
new T[d_bufLen_I];
82 d_doWriteBlock = doWriteBlock;
83 d_doFullRead = doFullRead;
85 d_readBlock = d_writeBlock = NULL;
87 DEBUG (std::cerr <<
"c_b(): buf len (items) = " << d_bufLen_
88 <<
", doWriteBlock = " << (d_doWriteBlock ?
"true" :
"false")
89 <<
", doFullRead = " << (d_doFullRead ?
"true" :
"false")
100 size_t retVal = d_n_avail_write_I;
106 size_t retVal = d_n_avail_read_I;
116 bzero (d_buffer, d_bufLen_I *
sizeof (T));
117 d_readNdx_I = d_writeNdx_I = d_n_avail_read_I = 0;
118 d_n_avail_write_I = d_bufLen_I;
119 delete_mutex_cond ();
154 DEBUG (std::cerr <<
"enqueue: buf = " << (
void*) buf
155 <<
", bufLen = " << bufLen_I
156 <<
", #av_wr = " << d_n_avail_write_I
157 <<
", #av_rd = " << d_n_avail_read_I << std::endl);
158 if (bufLen_I > d_bufLen_I) {
159 std::cerr <<
"ERROR: cannot add buffer longer ("
160 << bufLen_I <<
") than instantiated length ("
161 << d_bufLen_I <<
")." << std::endl;
162 throw std::runtime_error (
"circular_buffer::enqueue()");
168 throw std::runtime_error (
"circular_buffer::enqueue(): "
169 "input buffer is NULL.\n");
176 if (bufLen_I > d_n_avail_write_I) {
177 if (d_doWriteBlock) {
178 while (bufLen_I > d_n_avail_write_I) {
179 DEBUG (std::cerr <<
"enqueue: #len > #a, waiting." << std::endl);
182 d_writeBlock->wait (l);
185 DEBUG (std::cerr <<
"enqueue: #len > #a, aborting." << std::endl);
188 DEBUG (std::cerr <<
"enqueue: #len > #a, done waiting." << std::endl);
191 d_n_avail_read_I = d_bufLen_I - bufLen_I;
192 d_n_avail_write_I = bufLen_I;
193 DEBUG (std::cerr <<
"circular_buffer::enqueue: overflow" << std::endl);
197 size_t n_now_I = d_bufLen_I - d_writeNdx_I, n_start_I = 0;
198 if (n_now_I > bufLen_I)
200 else if (n_now_I < bufLen_I)
201 n_start_I = bufLen_I - n_now_I;
202 bcopy (buf, &(d_buffer[d_writeNdx_I]), n_now_I *
sizeof (T));
204 bcopy (&(buf[n_now_I]), d_buffer, n_start_I *
sizeof (T));
205 d_writeNdx_I = n_start_I;
207 d_writeNdx_I += n_now_I;
208 d_n_avail_read_I += bufLen_I;
209 d_n_avail_write_I -= bufLen_I;
210 d_readBlock->notify_one ();
236 DEBUG (std::cerr <<
"dequeue: buf = " << ((
void*) buf)
237 <<
", *bufLen = " << (*bufLen_I)
238 <<
", #av_wr = " << d_n_avail_write_I
239 <<
", #av_rd = " << d_n_avail_read_I << std::endl);
241 throw std::runtime_error (
"circular_buffer::dequeue(): "
242 "input bufLen pointer is NULL.\n");
244 throw std::runtime_error (
"circular_buffer::dequeue(): "
245 "input buffer pointer is NULL.\n");
246 size_t l_bufLen_I = *bufLen_I;
249 if (l_bufLen_I > d_bufLen_I) {
250 std::cerr <<
"ERROR: cannot remove buffer longer ("
251 << l_bufLen_I <<
") than instantiated length ("
252 << d_bufLen_I <<
")." << std::endl;
253 throw std::runtime_error (
"circular_buffer::dequeue()");
261 while (d_n_avail_read_I < l_bufLen_I) {
262 DEBUG (std::cerr <<
"dequeue: #a < #len, waiting." << std::endl);
265 d_readBlock->wait (l);
268 DEBUG (std::cerr <<
"dequeue: #a < #len, aborting." << std::endl);
271 DEBUG (std::cerr <<
"dequeue: #a < #len, done waiting." << std::endl);
274 while (d_n_avail_read_I == 0) {
275 DEBUG (std::cerr <<
"dequeue: #a == 0, waiting." << std::endl);
278 d_readBlock->wait (l);
281 DEBUG (std::cerr <<
"dequeue: #a == 0, aborting." << std::endl);
284 DEBUG (std::cerr <<
"dequeue: #a == 0, done waiting." << std::endl);
287 if (l_bufLen_I > d_n_avail_read_I)
288 l_bufLen_I = d_n_avail_read_I;
289 size_t n_now_I = d_bufLen_I - d_readNdx_I, n_start_I = 0;
290 if (n_now_I > l_bufLen_I)
291 n_now_I = l_bufLen_I;
292 else if (n_now_I < l_bufLen_I)
293 n_start_I = l_bufLen_I - n_now_I;
294 bcopy (&(d_buffer[d_readNdx_I]), buf, n_now_I *
sizeof (T));
296 bcopy (d_buffer, &(buf[n_now_I]), n_start_I *
sizeof (T));
297 d_readNdx_I = n_start_I;
299 d_readNdx_I += n_now_I;
300 *bufLen_I = l_bufLen_I;
301 d_n_avail_read_I -= l_bufLen_I;
302 d_n_avail_write_I += l_bufLen_I;
303 d_writeBlock->notify_one ();
310 d_writeBlock->notify_one ();
311 d_readBlock->notify_one ();