csplugincommon/sndsys/queue.h Source File (Crystal Space 2.0 Public API Reference)

| ## Public API Reference

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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