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