CrystalSpace

Public API Reference

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