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 00055 QUEUE_ERR_DUPE = -3 00056 } QueueErrorType; 00057 00058 00059 // Advance declaration of class QueueIterator 00060 template<typename T> class QueueIterator; 00061 00063 template<typename T> 00064 class QEntry 00065 { 00066 public: 00067 T * data; 00068 QEntry *next, *prev; 00069 }; 00070 00095 template<typename T> 00096 class Queue 00097 { 00098 public: 00099 00101 Queue() : 00102 m_pHead(0), m_pTail(0), m_EntryCount(0), m_bClosed(false), m_bDupeCheck(false) 00103 { 00104 00105 } 00106 00107 ~Queue() 00108 { 00109 Clear(); 00110 } 00111 00118 void Clear() 00119 { 00120 QEntry<T> *del; 00121 00122 CS::Threading::RecursiveMutexScopedLock lock (m_pAccessMutex); 00123 00124 while (m_pHead) 00125 { 00126 del=m_pHead; 00127 m_pHead=m_pHead->next; 00128 delete del; 00129 } 00130 m_pTail=0; 00131 00132 // Wake all waiting threads, queue is cleared 00133 m_pEntryReadyCondition.NotifyAll (); 00134 } 00135 00137 QueueErrorType QueueEntry(T* pData) 00138 { 00139 CS::Threading::RecursiveMutexScopedLock lock (m_pAccessMutex); 00140 00141 if (m_bClosed) return QUEUE_ERR_CLOSED; 00142 00143 if (m_bDupeCheck && Find(pData)) 00144 { 00145 return QUEUE_ERR_DUPE; 00146 } 00147 00148 QEntry<T> *pNewEntry= new QEntry<T>(); 00149 if (!pNewEntry) 00150 { 00151 return QUEUE_ERR_NOMEM; 00152 } 00153 pNewEntry->data=pData; 00154 pNewEntry->prev=m_pTail; 00155 pNewEntry->next=0; 00156 00157 if (!m_pTail) 00158 m_pHead=pNewEntry; 00159 else 00160 m_pTail->next=pNewEntry; 00161 m_pTail=pNewEntry; 00162 00163 00164 // Signal one waiting thread to wake up 00165 m_pEntryReadyCondition.NotifyOne (); 00166 00167 return QUEUE_SUCCESS; 00168 } 00169 00179 T * DequeueEntry(bool bWait=false) 00180 { 00181 QEntry<T> *pRemoved; 00182 T* pData=0; 00183 00184 CS::Threading::RecursiveMutexScopedLock lock (m_pAccessMutex); 00185 00186 // Wait for an entry to be available if specified 00187 if (!m_pHead && bWait) 00188 m_pEntryReadyCondition.Wait (m_pAccessMutex); 00189 00190 // Remove the m_pHead entry from the queue, shift 00191 // the head pointer to the next entry 00192 if (m_pHead) 00193 { 00194 00195 pRemoved=m_pHead; 00196 m_pHead=m_pHead->next; 00197 // Make sure the Next and Previous linked list pointers 00198 // remain valid. 00199 if (m_pHead) 00200 m_pHead->prev=0; 00201 else 00202 m_pTail=0; 00203 pData=pRemoved->data; 00204 // Delete the entry wrapper object 00205 delete pRemoved; 00206 } 00207 return pData; 00208 } 00209 00211 size_t Length() { return m_EntryCount; } 00212 00214 bool Find(T *data) 00215 { 00216 CS::Threading::RecursiveMutexScopedLock lock (m_pAccessMutex); 00217 QEntry<T> *cur=m_pHead; 00218 while (cur) 00219 { 00220 if (((cur->data)) == (data)) 00221 { 00222 return true; 00223 } 00224 cur=cur->next; 00225 } 00226 return false; 00227 } 00228 00230 void SetClosed(bool Closed) 00231 { 00232 CS::Threading::RecursiveMutexScopedLock lock (m_pAccessMutex); 00233 m_bClosed=Closed; 00234 } 00235 00238 bool GetClosed() 00239 { 00240 bool Closed; 00241 CS::Threading::RecursiveMutexScopedLock lock (m_pAccessMutex); 00242 Closed=m_bClosed; 00243 00244 return Closed; 00245 } 00246 00253 void SetDupecheck(bool Check) 00254 { 00255 CS::Threading::RecursiveMutexScopedLock lock (m_pAccessMutex); 00256 m_bDupeCheck=Check; 00257 } 00258 00260 bool GetDupecheck() 00261 { 00262 bool val; 00263 CS::Threading::RecursiveMutexScopedLock lock (m_pAccessMutex); 00264 val=m_bClosed; 00265 return val; 00266 } 00267 00272 QueueIterator<T>* GetIterator() 00273 { 00274 return new QueueIterator<T>(this); 00275 } 00276 00277 protected: 00279 QEntry<T> *m_pHead; 00281 QEntry<T> *m_pTail; 00283 size_t m_EntryCount; 00285 volatile bool m_bClosed; 00288 volatile bool m_bDupeCheck; 00289 00290 // A recursive mutex is used so that the duplicate entry check can hold a 00291 // lock m_EntryCount of 2 00292 00294 CS::Threading::RecursiveMutex m_pAccessMutex; 00296 CS::Threading::Condition m_pEntryReadyCondition; 00297 00298 00299 friend class QueueIterator<T>; 00300 }; 00301 00302 00303 00308 template<typename T> 00309 class QueueIterator 00310 { 00311 public: 00312 QueueIterator(Queue<T> *queue) 00313 { 00314 q=queue; 00315 current=0; 00316 q->Lock(); 00317 } 00318 00319 ~QueueIterator() 00320 { 00321 q->Unlock(); 00322 } 00323 00324 T * First() 00325 { 00326 current=q->m_pHead; 00327 return current; 00328 } 00329 00330 T * Last() 00331 { 00332 current=q->m_pTail; 00333 return current; 00334 } 00335 00336 T *Next() 00337 { 00338 if (current) current=current->next; 00339 return current; 00340 } 00341 00342 00343 T * Prev() 00344 { 00345 if (current) current=current->prev; 00346 return current; 00347 } 00348 00349 protected: 00350 QEntry<T> *current; 00351 Queue<T> *q; 00352 }; 00353 00354 00355 00356 } 00357 // END namespace CS::SndSys 00358 } 00359 // END namespace CS 00360 00361 00362 00363 #endif // #ifndef SNDSYS_QUEUE_H 00364
Generated for Crystal Space 1.2 by doxygen 1.4.7