00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef IXLIB_RING_QUEUE
00011 #define IXLIB_RING_QUEUE
00012
00013
00014
00015
00016 #include <ixlib_numeric.hh>
00017 #include <ixlib_array.hh>
00018
00019
00020
00021
00022 namespace ixion {
00032 template<class T,class Allocator = std::allocator<T> >
00033 class ring_queue {
00034 private:
00035 auto_array<T,Allocator> Data;
00036 TIndex Head;
00037 TIndex Tail;
00038
00039 public:
00040 ring_queue(TIndex capacity = 0)
00041 : Data(capacity),Head(0),Tail(0) {
00042 }
00043
00045 TSize capacity() const {
00046 return Data.capacity();
00047 }
00048
00050 TSize size() const {
00051 return NUM_CIRCLEDIST(Head,Tail,Data.capacity());
00052 }
00053
00055
00059 inline TSize pop(T *data,TSize maxcount = 1);
00060
00062 inline void push(T *data,TSize count = 1);
00063
00065
00068 inline T *popPointer(TSize &maxcount);
00069
00071 inline void popPointerCommit(TSize count);
00072
00074
00078 inline T *pushPointer(TSize &maxcount);
00079
00081 inline void pushPointerCommit(TSize count);
00082
00084 inline void allocate(TSize capacity) {
00085 Data.allocate(capacity);
00086 Head = 0;
00087 Tail = 0;
00088 }
00089 };
00090 }
00091
00092
00093
00094
00095 template<class T,class Allocator>
00096 ixion::TSize ixion::ring_queue<T,Allocator>::pop(T *data,TSize maxcount) {
00097 while (count) {
00098 TSize loopmax;
00099 T *buffer = popPointer(loopmax);
00100 if (loopmax == 0)
00101 EXGEN_THROW(EC_BUFFERUNDERFLOW)
00102
00103 TSize countdown = loopmax;
00104 while (countdown--)
00105 *data++ = *buffer++;
00106
00107 popPointerCommit(loopmax);
00108 count -= loopmax;
00109 }
00110 }
00111
00112
00113
00114
00115 template<class T,class Allocator>
00116 void ixion::ring_queue<T,Allocator>::push(T *data,TSize count) {
00117 TSize result = 0;
00118 while (count) {
00119 TSize loopmax;
00120 T *buffer = pushPointer(loopmax);
00121 if (loopmax == 0) break;
00122
00123 TSize countdown = loopmax;
00124 while (countdown--)
00125 *buffer++ = *data++;
00126
00127 pushPointerCommit(loopmax);
00128 count -= loopmax;
00129 result += loopmax;
00130 }
00131 return result;
00132 }
00133
00134
00135
00136
00137 template<class T,class Allocator>
00138 T *ixion::ring_queue<T,Allocator>::popPointer(TSize &maxcount) {
00139 if (Tail <= Head)
00140 maxcount = Head-Tail;
00141 else
00142 maxcount = Data.capacity() - Tail;
00143 return Data+Tail;
00144 }
00145
00146
00147
00148
00149 template<class T,class Allocator>
00150 void ixion::ring_queue<T,Allocator>::popPointerCommit(TSize count) {
00151 Tail = (Tail+count) % Data.capacity();
00152 }
00153
00154
00155
00156
00157 template<class T,class Allocator>
00158 T *ixion::ring_queue<T,Allocator>::pushPointer(TSize &maxcount) {
00159 if (Tail <= Head) {
00160 maxcount = Data.capacity() - Head;
00161 if (Tail == 0 && maxcount > 0) maxcount--;
00162 }
00163 else
00164
00165 maxcount = Tail - Head - 1;
00166 return Data+Head;
00167 }
00168
00169
00170
00171
00172 template<class T,class Allocator>
00173 void ixion::ring_queue<T,Allocator>::pushPointerCommit(TSize count) {
00174 Head = (Head+count) % Data.capacity();
00175 }
00176
00177
00178
00179
00180 #endif