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/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.1 by doxygen 1.5.3