summaryrefslogtreecommitdiff
path: root/src/ringbuffer.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/ringbuffer.h')
-rw-r--r--src/ringbuffer.h207
1 files changed, 163 insertions, 44 deletions
diff --git a/src/ringbuffer.h b/src/ringbuffer.h
index e984d18..04add42 100644
--- a/src/ringbuffer.h
+++ b/src/ringbuffer.h
@@ -10,97 +10,216 @@
10 10
11#include <memory> 11#include <memory>
12#include "bu/exceptionbase.h" 12#include "bu/exceptionbase.h"
13#include "bu/queue.h"
14#include "bu/sharedcore.h"
13 15
14namespace Bu 16namespace Bu
15{ 17{
16 /** 18 template<typename value, typename valuealloc> class RingBuffer;
17 *@ingroup Containers 19
18 */ 20 template<typename value, typename valuealloc>
19 template<typename value, typename valuealloc=std::allocator<value> > 21 class RingBufferCore
20 class RingBuffer
21 { 22 {
22 public: 23 friend class RingBuffer<value, valuealloc>;
23 RingBuffer( int nCapacity ) : 24 friend class SharedCore<RingBuffer<value, valuealloc>,
24 nCapacity( nCapacity ), 25 RingBufferCore<value, valuealloc> >;
25 nStart( -1 ), 26 private:
26 nEnd( -2 ) 27 RingBufferCore() :
28 iCapacity( 0 ),
29 iStart( -1 ),
30 iEnd( -2 ),
31 aData( NULL )
27 { 32 {
28 aData = va.allocate( nCapacity );
29 } 33 }
30 34
31 virtual ~RingBuffer() 35 virtual ~RingBufferCore()
32 { 36 {
33 for( int j = nStart; j < nEnd; j=(j+1%nCapacity) ) 37 clear();
34 {
35 va.destroy( &aData[j] );
36 }
37 va.deallocate( aData, nCapacity );
38 } 38 }
39 39
40 int getCapacity() 40 void init( int iNewCapacity )
41 { 41 {
42 return nCapacity; 42 if( iCapacity > 0 )
43 } 43 return;
44 44
45 bool isFilled() 45 iCapacity = iNewCapacity;
46 { 46 iStart = -1;
47 return (nStart == nEnd); 47 iEnd = -2;
48 aData = va.allocate( iCapacity );
48 } 49 }
49 50
50 bool isEmpty() 51 void clear()
51 { 52 {
52 return (nStart == -1); 53 for( int j = iStart; j < iEnd; j=(j+1%iCapacity) )
54 {
55 va.destroy( &aData[j] );
56 }
57 va.deallocate( aData, iCapacity );
58 aData = NULL;
59 iCapacity = 0;
53 } 60 }
54 61
55 void enqueue( const value &v ) 62 void enqueue( const value &v )
56 { 63 {
57 if( nStart == -1 ) 64 if( iStart == -1 )
58 { 65 {
59 nStart = 0; 66 iStart = 0;
60 nEnd = 1; 67 iEnd = 1;
61 va.construct( &aData[0], v ); 68 va.construct( &aData[0], v );
62 } 69 }
63 else if( nStart == nEnd ) 70 else if( iStart == iEnd )
64 { 71 {
65 throw ExceptionBase("Hey, it's full!"); 72 throw ExceptionBase("Hey, it's full!");
66 } 73 }
67 else 74 else
68 { 75 {
69 va.construct( &aData[nEnd], v ); 76 va.construct( &aData[iEnd], v );
70 nEnd = (nEnd+1)%nCapacity; 77 iEnd = (iEnd+1)%iCapacity;
71 } 78 }
72 } 79 }
73 80
74 value dequeue() 81 value dequeue()
75 { 82 {
76 if( nStart == -1 ) 83 if( iStart == -1 )
77 { 84 {
78 throw ExceptionBase("No data"); 85 throw ExceptionBase("No data");
79 } 86 }
80 else 87 else
81 { 88 {
82 value &v = aData[nStart]; 89 value &v = aData[iStart];
83 va.destroy( &aData[nStart] ); 90 va.destroy( &aData[iStart] );
84 nStart = (nStart+1)%nCapacity; 91 iStart = (iStart+1)%iCapacity;
85 if( nStart == nEnd ) 92 if( iStart == iEnd )
86 { 93 {
87 nStart = -1; 94 iStart = -1;
88 nEnd = -2; 95 iEnd = -2;
89 } 96 }
90 return v; 97 return v;
91 } 98 }
92 } 99 }
93 100
94 value &operator[]( int nIndex ) 101 value &get( int iIndex )
95 { 102 {
96 return aData[(nIndex+nStart)%nCapacity]; 103 return aData[(iIndex+iStart)%iCapacity];
97 } 104 }
98 105
99 private: 106 int getSize()
100 int nCapacity; 107 {
108 if( iStart < 0 )
109 return 0;
110 if( iEnd == iStart )
111 return iCapacity;
112 if( iEnd < iStart )
113 return iEnd-iStart;
114 return iCapacity-(iEnd-iStart);
115 }
116
117 int iCapacity;
118 int iStart, iEnd;
101 value *aData; 119 value *aData;
102 valuealloc va; 120 valuealloc va;
103 int nStart, nEnd; 121 };
122
123 /**
124 *@ingroup Containers
125 */
126 template<typename value, typename valuealloc=std::allocator<value> >
127 class RingBuffer : public Queue<value>, public SharedCore<
128 RingBuffer<value, valuealloc>,
129 RingBufferCore<value, valuealloc>
130 >
131 {
132 private:
133 typedef RingBuffer<value, valuealloc> MyType;
134 typedef RingBufferCore<value, valuealloc> Core;
135
136 protected:
137 using SharedCore<MyType, Core>::core;
138 using SharedCore<MyType, Core>::_hardCopy;
139 using SharedCore<MyType, Core>::_allocateCore;
140
141 public:
142 RingBuffer( int iCapacity )
143 {
144 core->init( iCapacity );
145 }
146
147 RingBuffer( const RingBuffer &rSrc ) :
148 SharedCore<MyType, Core>( rSrc )
149 {
150 }
151
152 virtual ~RingBuffer()
153 {
154 }
155
156 int getCapacity() const
157 {
158 return core->iCapacity;
159 }
160
161 bool isFilled() const
162 {
163 return (core->iStart == core->iEnd);
164 }
165
166 bool isEmpty() const
167 {
168 return (core->iStart == -1);
169 }
170
171 virtual void enqueue( const value &v )
172 {
173 _hardCopy();
174
175 core->enqueue( v );
176 }
177
178 virtual value dequeue()
179 {
180 _hardCopy();
181
182 return core->dequeue();
183 }
184
185 virtual int getSize() const
186 {
187 return core->getSize();
188 }
189
190 virtual value &peek()
191 {
192 _hardCopy();
193
194 return core->get( 0 );
195 }
196
197 virtual const value &peek() const
198 {
199 return core->get( 0 );
200 }
201
202 value &operator[]( int iIndex )
203 {
204 _hardCopy();
205
206 return core->get( iIndex );
207 }
208
209 protected:
210 virtual Core *_copyCore( Core *src )
211 {
212 Core *pRet = _allocateCore();
213
214 pRet->init( src->iCapacity );
215 int iSize = src->getSize();
216 for( int j = 0; j < iSize; j++ )
217 {
218 pRet->enqueue( src->get( j ) );
219 }
220
221 return pRet;
222 }
104 }; 223 };
105} 224}
106 225