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 
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.7.6.1