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/thread.h" 00030 00031 namespace CS 00032 { 00033 namespace SndSys 00034 { 00035 00037 typedef enum 00038 { 00040 QUEUE_SUCCESS = 0, 00041 00045 QUEUE_ERR_CLOSED = -1, 00046 00048 QUEUE_ERR_NOMEM = -2, 00049 00054 QUEUE_ERR_DUPE = -3 00055 } QueueErrorType; 00056 00057 00058 // Advance declaration of class QueueIterator 00059 template<typename T> class QueueIterator; 00060 00062 template<typename T> 00063 class QEntry 00064 { 00065 public: 00066 T * data; 00067 QEntry *next, *prev; 00068 }; 00069 00094 template<typename T> 00095 class Queue 00096 { 00097 public: 00098 00100 Queue() : 00101 m_pHead(0), m_pTail(0), m_EntryCount(0), m_bClosed(false), m_bDupeCheck(false) 00102 { 00103 // A recursive mutex is used so that the duplicate entry check can hold a 00104 // lock m_EntryCount of 2 00105 m_pAccessMutex = csMutex::Create(true); 00106 m_pEntryReadyCondition = csCondition::Create(); 00107 } 00108 00109 ~Queue() 00110 { 00111 Clear(); 00112 } 00113 00120 void Clear() 00121 { 00122 QEntry<T> *del; 00123 Lock(); 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->Signal(true); 00134 Unlock(); 00135 } 00136 00138 QueueErrorType QueueEntry(T* pData) 00139 { 00140 Lock(); 00141 00142 if (m_bClosed) return QUEUE_ERR_CLOSED; 00143 00144 if (m_bDupeCheck && Find(pData)) 00145 { 00146 Unlock(); 00147 return QUEUE_ERR_DUPE; 00148 } 00149 00150 QEntry<T> *pNewEntry= new QEntry<T>(); 00151 if (!pNewEntry) 00152 { 00153 Unlock(); 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->Signal(); 00169 00170 Unlock(); 00171 return QUEUE_SUCCESS; 00172 } 00173 00183 T * DequeueEntry(bool bWait=false) 00184 { 00185 QEntry<T> *pRemoved; 00186 T* pData=0; 00187 00188 Lock(); 00189 00190 // Wait for an entry to be available if specified 00191 if (!m_pHead && bWait) 00192 m_pEntryReadyCondition->Wait(m_pAccessMutex,0); 00193 00194 // Remove the m_pHead entry from the queue, shift 00195 // the head pointer to the next entry 00196 if (m_pHead) 00197 { 00198 00199 pRemoved=m_pHead; 00200 m_pHead=m_pHead->next; 00201 // Make sure the Next and Previous linked list pointers 00202 // remain valid. 00203 if (m_pHead) 00204 m_pHead->prev=0; 00205 else 00206 m_pTail=0; 00207 pData=pRemoved->data; 00208 // Delete the entry wrapper object 00209 delete pRemoved; 00210 } 00211 Unlock(); 00212 return pData; 00213 } 00214 00216 size_t Length() { return m_EntryCount; } 00217 00219 bool Find(T *data) 00220 { 00221 Lock(); 00222 QEntry<T> *cur=m_pHead; 00223 while (cur) 00224 { 00225 if (((cur->data)) == (data)) 00226 { 00227 Unlock(); 00228 return true; 00229 } 00230 cur=cur->next; 00231 } 00232 Unlock(); 00233 return false; 00234 } 00235 00237 void SetClosed(bool Closed) 00238 { 00239 Lock(); 00240 m_bClosed=Closed; 00241 Unlock(); 00242 } 00243 00246 bool GetClosed() 00247 { 00248 bool Closed; 00249 Lock(); 00250 Closed=m_bClosed; 00251 Unlock(); 00252 return Closed; 00253 } 00254 00261 void SetDupecheck(bool Check) 00262 { 00263 Lock(); 00264 m_bDupeCheck=Check; 00265 Unlock(); 00266 } 00267 00269 bool GetDupecheck() 00270 { 00271 bool val; 00272 Lock(); 00273 val=m_bClosed; 00274 Unlock(); 00275 return val; 00276 } 00277 00282 QueueIterator<T>* GetIterator() 00283 { 00284 return new QueueIterator<T>(this); 00285 } 00286 00287 protected: 00288 00290 inline void Lock() 00291 { 00292 m_pAccessMutex->LockWait(); 00293 } 00294 00296 inline void Unlock() 00297 { 00298 m_pAccessMutex->Release(); 00299 } 00300 00301 protected: 00303 QEntry<T> *m_pHead; 00305 QEntry<T> *m_pTail; 00307 size_t m_EntryCount; 00309 volatile bool m_bClosed; 00312 volatile bool m_bDupeCheck; 00313 00315 csRef<csMutex> m_pAccessMutex; 00317 csRef<csCondition> m_pEntryReadyCondition; 00318 00319 00320 friend class QueueIterator<T>; 00321 }; 00322 00323 00324 00329 template<typename T> 00330 class QueueIterator 00331 { 00332 public: 00333 QueueIterator(Queue<T> *queue) 00334 { 00335 q=queue; 00336 current=0; 00337 q->Lock(); 00338 } 00339 00340 ~QueueIterator() 00341 { 00342 q->Unlock(); 00343 } 00344 00345 T * First() 00346 { 00347 current=q->m_pHead; 00348 return current; 00349 } 00350 00351 T * Last() 00352 { 00353 current=q->m_pTail; 00354 return current; 00355 } 00356 00357 T *Next() 00358 { 00359 if (current) current=current->next; 00360 return current; 00361 } 00362 00363 00364 T * Prev() 00365 { 00366 if (current) current=current->prev; 00367 return current; 00368 } 00369 00370 protected: 00371 QEntry<T> *current; 00372 Queue<T> *q; 00373 }; 00374 00375 00376 00377 } 00378 // END namespace CS::SndSys 00379 } 00380 // END namespace CS 00381 00382 00383 00384 #endif // #ifndef SNDSYS_QUEUE_H 00385
Generated for Crystal Space by doxygen 1.4.7