Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #pragma once
00015
00019 #include "Alignment.h"
00020
00021 namespace kNet
00022 {
00023
00025
00033 template<typename T>
00034 class WaitFreeQueue
00035 {
00036 public:
00038 explicit WaitFreeQueue(size_t maxElements)
00039 :head(0), tail(0)
00040 {
00041 assert(IS_POW2(maxElements));
00042 assert(maxElements > 2);
00043 maxElements = (size_t)RoundUpToNextPow2((u32)maxElements);
00044
00045 data = new T[maxElements];
00046 maxElementsMask = maxElements - 1;
00047 }
00048
00049 ~WaitFreeQueue()
00050 {
00051 delete[] data;
00052 }
00053
00056 int Capacity() const { return maxElementsMask; }
00057
00060 int CapacityLeft() const { return Capacity() - Size(); }
00061
00063 bool Insert(const T &value)
00064 {
00065
00066 unsigned long tail_ = tail;
00067 unsigned long nextTail = (tail_ + 1) & maxElementsMask;
00068 if (nextTail == head)
00069 return false;
00070 data[tail_] = value;
00071 tail = nextTail;
00072
00073 return true;
00074 }
00075
00079 void InsertWithResize(const T &value)
00080 {
00081 bool success = Insert(value);
00082 if (!success)
00083 {
00084 DoubleCapacity();
00085 success = Insert(value);
00086 }
00087 assert(success);
00088 }
00089
00093 void Resize(size_t newSize)
00094 {
00095 assert(IS_POW2(newSize));
00096 newSize = (size_t)RoundUpToNextPow2((u32)newSize);
00097
00098 T *newData = new T[newSize];
00099 unsigned long newTail = 0;
00100 for(unsigned long i = 0; i < Size(); ++i)
00101 newData[newTail++] = *ItemAt(i);
00102 delete[] data;
00103 data = newData;
00104 head = 0;
00105 tail = newTail;
00106 maxElementsMask = newSize - 1;
00107 }
00108
00112 void DoubleCapacity() { Resize(2*(maxElementsMask+1)); }
00113
00115 T *Front()
00116 {
00117 if (head == tail)
00118 return 0;
00119 return &data[head];
00120 }
00121
00123 T *ItemAt(int index)
00124 {
00125 assert(index < (int)Size());
00126 return &data[(head + index) & maxElementsMask];
00127 }
00128
00130 const T *ItemAt(int index) const
00131 {
00132 assert(index < (int)Size());
00133 return &data[(head + index) & maxElementsMask];
00134 }
00135
00137 bool Contains(const T &item) const
00138 {
00139 for(int i = 0; i < (int)Size(); ++i)
00140 if (*ItemAt(i) == item)
00141 return true;
00142 return false;
00143 }
00144
00147 void EraseItemAt(int index)
00148 {
00149 if (index <= Size()>>1)
00150 EraseItemAtMoveFront(index);
00151 else
00152 EraseItemAtMoveBack(index);
00153 }
00154
00156 const T *Front() const
00157 {
00158 if (head == tail)
00159 return 0;
00160 return &data[head];
00161 }
00162
00164 T TakeFront()
00165 {
00166 T frontVal = *Front();
00167 PopFront();
00168 return frontVal;
00169 }
00170
00173 void Clear()
00174 {
00175 tail = head;
00176 }
00177
00179 unsigned long Size() const
00180 {
00181 unsigned long head_ = head;
00182 unsigned long tail_ = tail;
00183 if (tail_ >= head_)
00184 return tail_ - head_;
00185 else
00186 return maxElementsMask + 1 - (head_ - tail_);
00187 }
00188
00190 void PopFront()
00191 {
00192 assert(head != tail);
00193 if (head == tail)
00194 return;
00195 size_t head_ = (head + 1) & maxElementsMask;
00196 head = head_;
00197 }
00198
00199 private:
00200 T *data;
00202 unsigned long maxElementsMask;
00205 volatile unsigned long head;
00207 volatile unsigned long tail;
00208
00209 WaitFreeQueue(const WaitFreeQueue<T> &rhs);
00210 void operator=(const WaitFreeQueue<T> &rhs);
00211
00215 void EraseItemAtMoveFront(int index)
00216 {
00217 assert(Size() > 0);
00218 int numItemsToMove = index;
00219 for(int i = 0; i < numItemsToMove; ++i)
00220 data[(head+index + maxElementsMask+1 -i)&maxElementsMask] = data[(head+index + maxElementsMask+1 -i-1) &maxElementsMask];
00221 head = (head+1) & maxElementsMask;
00222 }
00223
00226 void EraseItemAtMoveBack(int index)
00227 {
00228 assert(Size() > 0);
00229 int numItemsToMove = Size()-1-index;
00230 for(int i = 0; i < numItemsToMove; ++i)
00231 data[(head+index+i)&maxElementsMask] = data[(head+index+i+1)&maxElementsMask];
00232 tail = (tail + maxElementsMask+1 - 1) & maxElementsMask;
00233 }
00234 };
00235
00236 template<typename T>
00237 bool ContainerUniqueAndNoNullElements(const WaitFreeQueue<T> &cont)
00238 {
00239 for(size_t i = 0; i < cont.Size(); ++i)
00240 for(size_t j = i+1; j < cont.Size(); ++j)
00241 if (*cont.ItemAt(i) == *cont.ItemAt(j) || *cont.ItemAt(i) == 0)
00242 return false;
00243 return true;
00244 }
00245
00246 }