66#include < memory>
77#include < iterator>
88#include < type_traits>
9+ #include < algorithm>
910
1011template <typename T>
1112class CircularBuffer {
@@ -28,6 +29,24 @@ class CircularBuffer {
2829 explicit CircularBuffer (size_t size)
2930 :_buff{std::unique_ptr<T[]>(new T[size])}, _max_size{size}{}
3031
32+ CircularBuffer (const CircularBuffer& other)
33+ :_buff{std::unique_ptr<T[]>(new T[other.capacity ()])},
34+ _max_size{other.capacity ()},
35+ _size{other._size },
36+ _head{other._head },
37+ _tail{other._tail },
38+ _full{other._full }{
39+
40+ std::copy (other.data (), other.data () + _max_size, _buff.get ());
41+ }
42+
43+ CircularBuffer& operator =(const CircularBuffer& other){
44+ _buff = std::unique_ptr<T[]>(new T[other.capacity ()]);
45+ _max_size = other.capacity ();
46+ std::copy (other.data (), other.data () + _max_size, _buff.get ());
47+ return *this ;
48+ }
49+
3150 void push_back (const value_type& data);
3251 void pop_front ();
3352 reference front ();
@@ -40,8 +59,12 @@ class CircularBuffer {
4059 size_type capacity () const ;
4160 size_type size () const ;
4261 size_type buffer_size () const {return sizeof (T)*_max_size;};
62+ const_pointer data () const { return _buff.get (); }
63+
4364 const_reference operator [](size_type index) const ;
4465 reference operator [](size_type index);
66+ const_reference at (size_type index) const ;
67+ reference at (size_type index);
4568
4669 iterator begin ();
4770 const_iterator begin () const ;
@@ -53,6 +76,7 @@ class CircularBuffer {
5376 void _decrement_bufferstate ();
5477 mutable std::mutex _mtx;
5578 std::unique_ptr<T[]> _buff;
79+
5680 size_type _head = 0 ;
5781 size_type _tail = 0 ;
5882 size_type _size = 0 ;
@@ -234,7 +258,8 @@ typename CircularBuffer<T>::reference CircularBuffer<T>::back() {
234258 std::lock_guard<std::mutex> _lck (_mtx);
235259 if (empty ())
236260 throw std::length_error (" back function called on empty buffer" );
237- return _buff[_head-1 ];
261+ // return _buff[_head - 1];
262+ return _head == 0 ? _buff[_max_size - 1 ] : _buff[_head - 1 ];
238263}
239264
240265template <typename T>
@@ -252,14 +277,15 @@ typename CircularBuffer<T>::const_reference CircularBuffer<T>::back() const{
252277 std::lock_guard<std::mutex> _lck (_mtx);
253278 if (empty ())
254279 throw std::length_error (" back function called on empty buffer" );
255- return _buff[_head - 1 ];
280+ // return _buff[_head - 1];
281+ return _head == 0 ? _buff[_max_size - 1 ] : _buff[_head - 1 ];
256282}
257283
258284template <typename T>
259285void CircularBuffer<T>::push_back(const T& data){
260286 std::lock_guard<std::mutex> _lck (_mtx);
261- if (full ())
262- _buff[_head ].~T ();
287+ // if(full())
288+ // _buff[_tail ].~T();
263289 _buff[_head] = data;
264290 _increment_bufferstate ();
265291}
@@ -271,32 +297,31 @@ void CircularBuffer<T>::_increment_bufferstate(){
271297 _tail = (_tail + 1 )%_max_size;
272298 else
273299 ++_size;
274- _head = (_head + 1 )%_max_size;
275- _full = (_head == _tail);
300+ _head = (_head + 1 )%_max_size;
276301}
277302
278303template <typename T>
279304inline
280305void CircularBuffer<T>::pop_front(){
281306 std::lock_guard<std::mutex> _lck (_mtx);
282307 if (empty ())
283- throw std::length_error (" pop_back called on empty buffer" );
308+ throw std::length_error (" pop_front called on empty buffer" );
284309 _decrement_bufferstate ();
285310}
286311
287312template <typename T>
288313inline
289314void CircularBuffer<T>::_decrement_bufferstate(){
290- // _full = false;
291315 --_size;
292316 _tail = (_tail + 1 )%_max_size;
293317}
294318
295319template <typename T>
296320inline
297321typename CircularBuffer<T>::reference CircularBuffer<T>::operator [](size_t index) {
298- if ((index<0 )||(index>_max_size))
299- throw std::out_of_range (" Index is out of Range of buffer size" );
322+ std::lock_guard<std::mutex> _lck (_mtx);
323+ if ((index<0 )||(index>=_max_size))
324+ throw std::out_of_range (" Index is out of Range of buffer capacity" );
300325 index += _tail;
301326 index %= _max_size;
302327 return _buff[index];
@@ -305,7 +330,30 @@ typename CircularBuffer<T>::reference CircularBuffer<T>::operator[](size_t index
305330template <typename T>
306331inline
307332typename CircularBuffer<T>::const_reference CircularBuffer<T>::operator [](size_t index) const {
308- if ((index<0 )||(index>_max_size))
333+ std::lock_guard<std::mutex> _lck (_mtx);
334+ if ((index<0 )||(index>=_max_size))
335+ throw std::out_of_range (" Index is out of Range of buffer capacity" );
336+ index += _tail;
337+ index %= _max_size;
338+ return _buff[index];
339+ }
340+
341+ template <typename T>
342+ inline
343+ typename CircularBuffer<T>::reference CircularBuffer<T>::at(size_t index) {
344+ std::lock_guard<std::mutex> _lck (_mtx);
345+ if ((index<0 )||(index>=_size))
346+ throw std::out_of_range (" Index is out of Range of buffer size" );
347+ index += _tail;
348+ index %= _max_size;
349+ return _buff[index];
350+ }
351+
352+ template <typename T>
353+ inline
354+ typename CircularBuffer<T>::const_reference CircularBuffer<T>::at(size_t index) const {
355+ std::lock_guard<std::mutex> _lck (_mtx);
356+ if ((index<0 )||(index>=_size))
309357 throw std::out_of_range (" Index is out of Range of buffer size" );
310358 index += _tail;
311359 index %= _max_size;
0 commit comments