summaryrefslogtreecommitdiff
path: root/src/stable/ringbuffer.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/stable/ringbuffer.h')
-rw-r--r--src/stable/ringbuffer.h228
1 files changed, 228 insertions, 0 deletions
diff --git a/src/stable/ringbuffer.h b/src/stable/ringbuffer.h
new file mode 100644
index 0000000..f43773d
--- /dev/null
+++ b/src/stable/ringbuffer.h
@@ -0,0 +1,228 @@
1/*
2 * Copyright (C) 2007-2011 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#ifndef BU_RING_BUFFER_H
9#define BU_RING_BUFFER_H
10
11#include <memory>
12#include "bu/exceptionbase.h"
13#include "bu/queue.h"
14#include "bu/sharedcore.h"
15
16namespace Bu
17{
18 template<typename value, typename valuealloc> class RingBuffer;
19
20 /** @cond DEVEL */
21 template<typename value, typename valuealloc>
22 class RingBufferCore
23 {
24 friend class RingBuffer<value, valuealloc>;
25 friend class SharedCore<RingBuffer<value, valuealloc>,
26 RingBufferCore<value, valuealloc> >;
27 private:
28 RingBufferCore() :
29 iCapacity( 0 ),
30 iStart( -1 ),
31 iEnd( -2 ),
32 aData( NULL )
33 {
34 }
35
36 virtual ~RingBufferCore()
37 {
38 clear();
39 }
40
41 void init( int iNewCapacity )
42 {
43 if( iCapacity > 0 )
44 return;
45
46 iCapacity = iNewCapacity;
47 iStart = -1;
48 iEnd = -2;
49 aData = va.allocate( iCapacity );
50 }
51
52 void clear()
53 {
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;
61 }
62
63 void enqueue( const value &v )
64 {
65 if( iStart == -1 )
66 {
67 iStart = 0;
68 iEnd = 1;
69 va.construct( &aData[0], v );
70 }
71 else if( iStart == iEnd )
72 {
73 throw ExceptionBase("Hey, it's full!");
74 }
75 else
76 {
77 va.construct( &aData[iEnd], v );
78 iEnd = (iEnd+1)%iCapacity;
79 }
80 }
81
82 value dequeue()
83 {
84 if( iStart == -1 )
85 {
86 throw ExceptionBase("No data");
87 }
88 else
89 {
90 value &v = aData[iStart];
91 va.destroy( &aData[iStart] );
92 iStart = (iStart+1)%iCapacity;
93 if( iStart == iEnd )
94 {
95 iStart = -1;
96 iEnd = -2;
97 }
98 return v;
99 }
100 }
101
102 value &get( int iIndex )
103 {
104 return aData[(iIndex+iStart)%iCapacity];
105 }
106
107 int getSize()
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;
120 value *aData;
121 valuealloc va;
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 }
225 };
226}
227
228#endif