00001 #ifndef __LDK_LOCKLESSQUEUE_HH__
00002 #define __LDK_LOCKLESSQUEUE_HH__
00003
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00028
00033
00034 #include "LDK/Exceptions.h"
00035 #include "LDK/Atomic.h"
00036 #include <memory.h>
00037
00038 namespace LDK
00039 {
00061 template <class T>
00062 class LocklessQueue
00063 {
00064 struct QType
00065 {
00066 AtomicCount mHead;
00067 AtomicCount mTail;
00068 T* mBuffer;
00069 Atomic<bool> mOverflow;
00070
00071 inline QType(size_t size) : mHead(0),
00072 mTail(0),
00073 mBuffer(NULL),
00074 mOverflow(false)
00075 {
00076 mBuffer = reinterpret_cast<T*>(malloc(sizeof(T)*size));
00077 if(!mBuffer)
00078 throw LDK_BADALLOC_ERROR;
00079 }
00080
00081 inline ~QType()
00082 {
00083 if(mBuffer)
00084 ::free(mBuffer);
00085 }
00086
00087 inline const T* operator[](size_t idx) const
00088 {
00089 return &mBuffer[idx];
00090 }
00091
00092 inline T* operator[](size_t idx)
00093 {
00094 return &mBuffer[idx];
00095 }
00096 };
00097
00098 QType* mQueue;
00099 const size_t mSize;
00100
00101 public:
00105 inline LocklessQueue(size_t size) : mQueue(NULL),
00106 mSize(size+1)
00107 {
00108 mQueue = new QType(mSize);
00109 }
00110
00111 inline ~LocklessQueue()
00112 {
00113 if(mQueue)
00114 delete mQueue;
00115 }
00116
00121 inline void enqueue(const T& msg)
00122 {
00123 size_t tail = mQueue->mTail;
00124 memcpy((*mQueue)[tail], &msg, sizeof(T));
00125 tail++;
00126 if(tail == mSize)
00127 tail = 0;
00128 if(tail == mQueue->mHead)
00129 {
00130 mQueue->mOverflow = true;
00131 throw LDK_LENGTH_ERROR("LocklessQueue overflow");
00132 }
00133 mQueue->mTail = tail;
00134 }
00135
00140 inline void enqueue(const T* msg)
00141 {
00142 enqueue(*msg);
00143 }
00144
00149 inline void dequeue(T& msg)
00150 {
00151 if(mQueue->mOverflow)
00152 {
00153 mQueue->mOverflow = false;
00154 return;
00155 }
00156
00157 size_t head = mQueue->mHead;
00158
00159 if(head == mQueue->mTail)
00160 throw LDK_LENGTH_ERROR("LocklessQueue empty");
00161 memcpy(&msg, (*mQueue)[head], sizeof(T));
00162 head++;
00163 if(head == mSize)
00164 head = 0;
00165 mQueue->mHead = head;
00166 }
00167
00172 inline void dequeue(T* msg)
00173 {
00174 dequeue(*msg);
00175 }
00176
00179 inline bool full() const
00180 {
00181 size_t tail = mQueue->mTail + 1;
00182 if(tail == mSize)
00183 tail = 0;
00184 return (tail == mQueue->mHead);
00185 }
00186
00189 inline bool empty() const
00190 {
00191 return (mQueue->mHead == mQueue->mTail);
00192 }
00193
00196 inline const T* peek() const
00197 {
00198 size_t head = mQueue->mHead;
00199 if(head == mQueue->mTail)
00200 return NULL;
00201 return (*mQueue)[head];
00202 }
00203
00204 inline void clear()
00205 {
00206 mQueue->mTail = 0;
00207 mQueue->mHead = 0;
00208 mQueue->mOverflow = 0;
00209 }
00210 };
00211
00212 }
00213
00214 #endif //__LDK_LOCKLESSQUEUE_HH__