csplugincommon/sndsys/queue.h
Go to the documentation of this file.00001 /* 00002 Copyright (C) 2004 by Andrew Mann 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public 00015 License along with this library; if not, write to the Free 00016 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00017 */ 00018 00019 00025 #ifndef SNDSYS_QUEUE_H 00026 #define SNDSYS_QUEUE_H 00027 00028 00029 #include "csutil/threading/mutex.h" 00030 #include "csutil/threading/condition.h" 00031 00032 namespace CS 00033 { 00034 namespace SndSys 00035 { 00036 00038 typedef enum 00039 { 00041 QUEUE_SUCCESS = 0, 00042 00046 QUEUE_ERR_CLOSED = -1, 00047 00049 QUEUE_ERR_NOMEM = -2, 00050 00056 QUEUE_ERR_DUPE = -3 00057 } QueueErrorType; 00058 00059 00060 // Advance declaration of class QueueIterator 00061 template<typename T> class QueueIterator; 00062 00064 template<typename T> 00065 class QEntry 00066 { 00067 public: 00068 T * data; 00069 QEntry *next, *prev; 00070 }; 00071 00098 template<typename T> 00099 class Queue 00100 { 00101 public: 00102 00104 Queue() : 00105 m_pHead(0), m_pTail(0), m_EntryCount(0), m_bClosed(false), m_bDupeCheck(false) 00106 { 00107 00108 } 00109 00110 ~Queue() 00111 { 00112 Clear(); 00113 } 00114 00121 void Clear() 00122 { 00123 QEntry<T> *del; 00124 00125 CS::Threading::RecursiveMutexScopedLock lock (m_pAccessMutex); 00126 00127 while (m_pHead) 00128 { 00129 del=m_pHead; 00130 m_pHead=m_pHead->next; 00131 delete del; 00132 } 00133 m_pTail=0; 00134 00135 // Wake all waiting threads, queue is cleared 00136 m_pEntryReadyCondition.NotifyAll (); 00137 } 00138 00140 QueueErrorType QueueEntry(T* pData) 00141 { 00142 CS::Threading::RecursiveMutexScopedLock lock (m_pAccessMutex); 00143 00144 if (m_bClosed) return QUEUE_ERR_CLOSED; 00145 00146 if (m_bDupeCheck && Find(pData)) 00147 { 00148 return QUEUE_ERR_DUPE; 00149 } 00150 00151 QEntry<T> *pNewEntry= new QEntry<T>(); 00152 if (!pNewEntry) 00153 { 00154 return QUEUE_ERR_NOMEM; 00155 } 00156 pNewEntry->data=pData; 00157 pNewEntry->prev=m_pTail; 00158 pNewEntry->next=0; 00159 00160 if (!m_pTail) 00161 m_pHead=pNewEntry; 00162 else 00163 m_pTail->next=pNewEntry; 00164 m_pTail=pNewEntry; 00165 00166 00167 // Signal one waiting thread to wake up 00168 m_pEntryReadyCondition.NotifyOne (); 00169 00170 return QUEUE_SUCCESS; 00171 } 00172 00182 T * DequeueEntry(bool bWait=false) 00183 { 00184 QEntry<T> *pRemoved; 00185 T* pData=0; 00186 00187 CS::Threading::RecursiveMutexScopedLock lock (m_pAccessMutex); 00188 00189 // Wait for an entry to be available if specified 00190 if (!m_pHead && bWait) 00191 m_pEntryReadyCondition.Wait (m_pAccessMutex); 00192 00193 // Remove the m_pHead entry from the queue, shift 00194 // the head pointer to the next entry 00195 if (m_pHead) 00196 { 00197 00198 pRemoved=m_pHead; 00199 m_pHead=m_pHead->next; 00200 // Make sure the Next and Previous linked list pointers 00201 // remain valid. 00202 if (m_pHead) 00203 m_pHead->prev=0; 00204 else 00205 m_pTail=0; 00206 pData=pRemoved->data; 00207 // Delete the entry wrapper object 00208 delete pRemoved; 00209 } 00210 return pData; 00211 } 00212 00214 size_t Length() { return m_EntryCount; } 00215 00217 bool Find(T *data) 00218 { 00219 CS::Threading::RecursiveMutexScopedLock lock (m_pAccessMutex); 00220 QEntry<T> *cur=m_pHead; 00221 while (cur) 00222 { 00223 if (((cur->data)) == (data)) 00224 { 00225 return true; 00226 } 00227 cur=cur->next; 00228 } 00229 return false; 00230 } 00231 00233 void SetClosed(bool Closed) 00234 { 00235 CS::Threading::RecursiveMutexScopedLock lock (m_pAccessMutex); 00236 m_bClosed=Closed; 00237 } 00238 00241 bool GetClosed() 00242 { 00243 bool Closed; 00244 CS::Threading::RecursiveMutexScopedLock lock (m_pAccessMutex); 00245 Closed=m_bClosed; 00246 00247 return Closed; 00248 } 00249 00256 void SetDupecheck(bool Check) 00257 { 00258 CS::Threading::RecursiveMutexScopedLock lock (m_pAccessMutex); 00259 m_bDupeCheck=Check; 00260 } 00261 00263 bool GetDupecheck() 00264 { 00265 bool val; 00266 CS::Threading::RecursiveMutexScopedLock lock (m_pAccessMutex); 00267 val=m_bClosed; 00268 return val; 00269 } 00270 00275 QueueIterator<T>* GetIterator() 00276 { 00277 return new QueueIterator<T>(this); 00278 } 00279 00280 protected: 00282 QEntry<T> *m_pHead; 00284 QEntry<T> *m_pTail; 00286 size_t m_EntryCount; 00288 volatile bool m_bClosed; 00291 volatile bool m_bDupeCheck; 00292 00293 // A recursive mutex is used so that the duplicate entry check can hold a 00294 // lock m_EntryCount of 2 00295 00297 CS::Threading::RecursiveMutex m_pAccessMutex; 00299 CS::Threading::Condition m_pEntryReadyCondition; 00300 00301 00302 friend class QueueIterator<T>; 00303 }; 00304 00305 00306 00311 template<typename T> 00312 class QueueIterator 00313 { 00314 public: 00315 QueueIterator(Queue<T> *queue) 00316 { 00317 q=queue; 00318 current=0; 00319 q->Lock(); 00320 } 00321 00322 ~QueueIterator() 00323 { 00324 q->Unlock(); 00325 } 00326 00327 T * First() 00328 { 00329 current=q->m_pHead; 00330 return current; 00331 } 00332 00333 T * Last() 00334 { 00335 current=q->m_pTail; 00336 return current; 00337 } 00338 00339 T *Next() 00340 { 00341 if (current) current=current->next; 00342 return current; 00343 } 00344 00345 00346 T * Prev() 00347 { 00348 if (current) current=current->prev; 00349 return current; 00350 } 00351 00352 protected: 00353 QEntry<T> *current; 00354 Queue<T> *q; 00355 }; 00356 00357 00358 00359 } 00360 // END namespace CS::SndSys 00361 } 00362 // END namespace CS 00363 00364 00365 00366 #endif // #ifndef SNDSYS_QUEUE_H 00367
Generated for Crystal Space 2.0 by doxygen 1.6.1