Allolib  1.0
C++ Components For Interactive Multimedia
al_SingleRWRingBuffer.hpp
1 #ifndef INCLUDE_AL_SINGLE_READER_WRITER_RING_BUFFER_HPP
2 #define INCLUDE_AL_SINGLE_READER_WRITER_RING_BUFFER_HPP
3 
4 /* Allocore --
5  Multimedia / virtual environment application class library
6 
7  Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology,
8  UCSB. Copyright (C) 2012. The Regents of the University of California. All
9  rights reserved.
10 
11  Redistribution and use in source and binary forms, with or without
12  modification, are permitted provided that the following conditions are
13  met:
14 
15  Redistributions of source code must retain the above copyright
16  notice, this list of conditions and the following disclaimer.
17 
18  Redistributions in binary form must reproduce the above
19  copyright notice, this list of conditions and the following disclaimer in the
20  documentation and/or other materials provided with the
21  distribution.
22 
23  Neither the name of the University of California nor the names
24  of its contributors may be used to endorse or promote products derived from
25  this software without specific prior written permission.
26 
27  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
28  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
31  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
34  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
36  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
37  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 
39 
40  File description:
41  Passing data between a pair of threads without locking
42 
43  File author(s):
44  Graham Wakefield, 2010, grrrwaaa@gmail.com
45 */
46 
47 #include <inttypes.h>
48 #include <cstring>
49 
50 //#include "allocore/system/pstdint.h"
51 
52 namespace al {
53 
63  public:
66  SingleRWRingBuffer(size_t sz = 256);
67 
69 
72  size_t writeSpace() const;
73 
76  size_t readSpace() const;
77 
81  size_t write(const char* src, size_t sz);
82 
86  size_t read(char* dst, size_t sz);
87 
91  size_t peek(char* dst, size_t sz);
92 
95  void clear() { mRead = mWrite; }
96 
97  protected:
98  size_t mSize, mWrap;
99  size_t mRead, mWrite;
100  char* mData;
101 };
102 
103 inline uint32_t next_power_of_two(uint32_t v) {
104  --v;
105  v |= v >> 1;
106  v |= v >> 2;
107  v |= v >> 4;
108  v |= v >> 8;
109  v |= v >> 16;
110  return v + 1;
111 }
112 
114  : mSize(size_t(next_power_of_two(uint32_t(sz)))),
115  mWrap(mSize - 1),
116  mRead(0),
117  mWrite(0) {
118  mData = new char[mSize];
119 }
120 
121 inline SingleRWRingBuffer ::~SingleRWRingBuffer() { delete[] mData; }
122 
123 inline size_t SingleRWRingBuffer ::writeSpace() const {
124  const size_t r = mRead;
125  const size_t w = mWrite;
126  if (r == w) return mWrap;
127  return ((mSize + (r - w)) & mWrap) - 1;
128 }
129 
130 inline size_t SingleRWRingBuffer ::readSpace() const {
131  const size_t r = mRead;
132  const size_t w = mWrite;
133  return (mSize + (w - r)) & mWrap;
134 }
135 
136 inline size_t SingleRWRingBuffer ::write(const char* src, size_t sz) {
137  size_t space = writeSpace();
138  sz = sz > space ? space : sz;
139  if (sz == 0) return 0;
140 
141  size_t w = mWrite;
142  size_t end = w + sz;
143 
144  if (end < mSize) {
145  memcpy(mData + w, src, sz);
146  } else {
147  size_t split = mSize - w;
148  end &= mWrap;
149  memcpy(mData + w, src, split);
150  memcpy(mData, src + split, end);
151  }
152 
153  mWrite = end;
154  return sz;
155 }
156 
157 inline size_t SingleRWRingBuffer ::read(char* dst, size_t sz) {
158  size_t space = readSpace();
159  sz = sz > space ? space : sz;
160  if (sz == 0) return 0;
161 
162  size_t r = mRead;
163  size_t end = r + sz;
164 
165  if (end < mSize) {
166  memcpy(dst, mData + r, sz);
167  } else {
168  size_t split = mSize - r;
169  end &= mWrap;
170  memcpy(dst, mData + r, split);
171  memcpy(dst + split, mData, end);
172  }
173 
174  mRead = end;
175  return sz;
176 }
177 
178 inline size_t SingleRWRingBuffer ::peek(char* dst, size_t sz) {
179  size_t space = readSpace();
180  sz = sz > space ? space : sz;
181  if (sz == 0) return 0;
182 
183  size_t r = mRead;
184  size_t end = r + sz;
185 
186  if (end < mSize) {
187  memcpy(dst, mData + r, sz);
188  } else {
189  size_t split = mSize - r;
190  end &= mWrap;
191  memcpy(dst, mData + r, split);
192  memcpy(dst + split, mData, end);
193  }
194  return sz;
195 }
196 
197 } // namespace al
198 
199 #endif /* include guard */
size_t peek(char *dst, size_t sz)
size_t read(char *dst, size_t sz)
size_t write(const char *src, size_t sz)
Definition: al_App.hpp:23