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

| ## Public API Reference

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

- 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/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