14 RingBuffer::RingBuffer(size_t sz
, size_t elem_sz
)
15 : mWritePtr(0), mReadPtr(0), mSize(0), mSizeMask(0), mElemSize(elem_sz
)
18 size_t power_of_two
= 1;
21 power_of_two
= sz
- 1;
22 power_of_two
|= power_of_two
>>1;
23 power_of_two
|= power_of_two
>>2;
24 power_of_two
|= power_of_two
>>4;
25 power_of_two
|= power_of_two
>>8;
26 power_of_two
|= power_of_two
>>16;
27 if(sizeof(power_of_two
) > 4)
28 power_of_two
|= power_of_two
>>32;
31 if(power_of_two
< sz
|| std::numeric_limits
<size_t>::max()/elem_sz
<= power_of_two
)
32 throw std::bad_alloc();
35 mSizeMask
= mSize
- 1;
37 mBuffer
= std::unique_ptr
<char[]>(new char[mSize
*mElemSize
]);
38 std::fill(&(mBuffer
[0]), &(mBuffer
[mSize
*mElemSize
]), 0);
41 void RingBuffer::reset()
45 std::fill(&(mBuffer
[0]), &(mBuffer
[mSize
*mElemSize
]), 0);
48 size_t RingBuffer::read_space() const
50 size_t w
= mWritePtr
.load();
51 size_t r
= mReadPtr
.load();
52 return (mSize
+w
-r
) & mSizeMask
;
55 size_t RingBuffer::write_space() const
57 size_t w
= mWritePtr
.load();
58 size_t r
= mReadPtr
.load();
59 return (mSize
+r
-w
-1) & mSizeMask
;
62 size_t RingBuffer::read(char* dest
, size_t cnt
)
70 read_ptr
= mReadPtr
.load();
71 free_cnt
= (mSize
+mWritePtr
.load()-read_ptr
) & mSizeMask
;
72 if(free_cnt
== 0) return 0;
74 to_read
= (cnt
> free_cnt
) ? free_cnt
: cnt
;
75 cnt2
= read_ptr
+ to_read
;
78 n1
= mSize
- read_ptr
;
79 n2
= cnt2
& mSizeMask
;
80 memcpy(dest
, &(mBuffer
[read_ptr
*mElemSize
]), n1
*mElemSize
);
81 memcpy(dest
+ n1
*mElemSize
, &(mBuffer
[0]), n2
*mElemSize
);
82 mReadPtr
.store((read_ptr
+ n1
+ n2
) & mSizeMask
);
87 memcpy(dest
, &(mBuffer
[read_ptr
*mElemSize
]), n1
*mElemSize
);
88 mReadPtr
.store((read_ptr
+ n1
) & mSizeMask
);
94 size_t RingBuffer::peek(char* dest
, size_t cnt
)
102 read_ptr
= mReadPtr
.load();
103 free_cnt
= (mSize
+mWritePtr
.load()-read_ptr
) & mSizeMask
;
104 if(free_cnt
== 0) return 0;
106 to_read
= (cnt
> free_cnt
) ? free_cnt
: cnt
;
107 cnt2
= read_ptr
+ to_read
;
110 n1
= mSize
- read_ptr
;
111 n2
= cnt2
& mSizeMask
;
112 memcpy(dest
, &(mBuffer
[read_ptr
*mElemSize
]), n1
*mElemSize
);
113 memcpy(dest
+ n1
*mElemSize
, &(mBuffer
[0]), n2
*mElemSize
);
118 memcpy(dest
, &(mBuffer
[read_ptr
*mElemSize
]), n1
*mElemSize
);
124 size_t RingBuffer::write(const char* src
, size_t cnt
)
132 write_ptr
= mWritePtr
.load();
133 free_cnt
= (mSize
+mReadPtr
.load()-write_ptr
-1) & mSizeMask
;
134 if(free_cnt
== 0) return 0;
136 to_write
= (cnt
> free_cnt
) ? free_cnt
: cnt
;
137 cnt2
= write_ptr
+ to_write
;
140 n1
= mSize
- write_ptr
;
141 n2
= cnt2
& mSizeMask
;
142 memcpy(&(mBuffer
[write_ptr
*mElemSize
]), src
, n1
*mElemSize
);
143 memcpy(&(mBuffer
[0]), src
+ n1
*mElemSize
, n2
*mElemSize
);
144 mWritePtr
.store((write_ptr
+ n1
+ n2
) & mSizeMask
);
149 memcpy(&(mBuffer
[write_ptr
*mElemSize
]), src
, n1
*mElemSize
);
150 mWritePtr
.store((write_ptr
+ n1
) & mSizeMask
);
156 void RingBuffer::read_advance(size_t cnt
)
158 size_t tmp
= (mReadPtr
.load() + cnt
) & mSizeMask
;
162 void RingBuffer::write_advance(size_t cnt
)
164 size_t tmp
= (mWritePtr
.load() + cnt
) & mSizeMask
;
165 mWritePtr
.store(tmp
);
168 Array
<RingBuffer::Data
,2> RingBuffer::get_read_vector() const
175 w
= mWritePtr
.load();
177 free_cnt
= (mSize
+w
-r
) & mSizeMask
;
182 /* Two part vector: the rest of the buffer after the current write ptr,
183 * plus some from the start of the buffer. */
184 vec
[0].buf
= &(mBuffer
[r
*mElemSize
]);
185 vec
[0].len
= mSize
- r
;
186 vec
[1].buf
= &(mBuffer
[0]);
187 vec
[1].len
= cnt2
& mSizeMask
;
191 /* Single part vector: just the rest of the buffer */
192 vec
[0].buf
= &(mBuffer
[r
*mElemSize
]);
193 vec
[0].len
= free_cnt
;
194 vec
[1].buf
= nullptr;
201 Array
<RingBuffer::Data
,2> RingBuffer::get_write_vector() const
208 w
= mWritePtr
.load();
210 free_cnt
= (mSize
+r
-w
-1) & mSizeMask
;
215 /* Two part vector: the rest of the buffer after the current write ptr,
216 * plus some from the start of the buffer. */
217 vec
[0].buf
= &(mBuffer
[w
*mElemSize
]);
218 vec
[0].len
= mSize
- w
;
219 vec
[1].buf
= &(mBuffer
[0]);
220 vec
[1].len
= cnt2
& mSizeMask
;
224 vec
[0].buf
= &(mBuffer
[w
*mElemSize
]);
225 vec
[0].len
= free_cnt
;
226 vec
[1].buf
= nullptr;