Google

Main Page   Class Hierarchy   Compound List   File List   Compound Members  

csqueue.h

00001 /*
00002           A thread safe general purpose queue.
00003           Copyright (C) 2001 by Michael H. Voase
00004           Based on csEventQueue (c) 1998 1999, Andrew Zablotony.
00005 
00006           This library is free software; you can redistribute it and/or
00007           modify it under the terms of the GNU Library General Public
00008           License as published by the Free Software Foundation; either
00009           version 2 of the License, or (at your option) any later version.
00010 
00011           This library is distributed in the hope that it will be useful,
00012           but WITHOUT ANY WARRANTY; without even the implied warranty of
00013           MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00014           Library General Public License for more details.
00015 
00016           You should have received a copy of the GNU Library General Public
00017           License along with this library; if not, write to the Free
00018           Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 
00021 #ifndef __CSQUEUE_H__
00022 #define __CSQUEUE_H__
00023 
00024 /*
00025  *      A general purpose thread safe queue. You may use this queue directly
00026  *      by using the CS_DECLARE_TYPED_QUEUE( QueueType, Content type ). This is
00027  *      loosely based on csEventQueue, but does not specifically use iEvent.
00028  *      Place the declare typed queue somewhere in a header file then place
00029  *      declare typed queue base in a code page to complete the macro.
00030  */
00031 
00032 #define CS_DECLARE_TYPED_QUEUE( NAME, TYPE, DEF_QUEUE_LENGTH ) \
00033 class NAME \
00034 { \
00035   volatile TYPE **Content; \
00036   volatile int qHead, qTail; \
00037   volatile int Length; \
00038   volatile int Spinlock; \
00039 public: \
00040   NAME ( int len = DEF_QUEUE_LENGTH ); \
00041   virtual ~NAME(); \
00042   void Put( TYPE *item ); \
00043   TYPE *Get(); \
00044   void Clear(); \
00045   bool IsEmpty() { return qHead == qTail; } \
00046 private: \
00047   void Resize( int length ); \
00048   inline void Lock() \
00049   { while (Spinlock) {} Spinlock++; } \
00050   inline void Unlock() \
00051   { Spinlock--; } \
00052 };
00053 
00054 
00055 
00056 #define CS_DECLARE_TYPED_QUEUE_BASE( NAME, TYPE, DEF_QUEUE_LENGTH ) \
00057 NAME::NAME ( int len ) : Content(NULL), Length(0), Spinlock(0) \
00058 { \
00059   qHead = qTail = 0; \
00060   Resize( len ); \
00061 } \
00062 NAME::~NAME () \
00063 { \
00064   Clear(); \
00065   if ( Content ) \
00066         delete[] Content; \
00067 } \
00068 void NAME::Put( TYPE *item ) \
00069 { \
00070 again: \
00071   Lock(); \
00072   int newHead = qHead + 1; \
00073   if ( newHead == Length ) \
00074         newHead = 0; \
00075   if ( newHead == qTail ) \
00076   { \
00077         Unlock(); \
00078         Resize( Length + 2 ); \
00079         goto again; \
00080   } \
00081   Content [ qHead ] = item; \
00082   qHead = newHead; \
00083   Unlock(); \
00084 } \
00085 TYPE *NAME::Get() \
00086 { \
00087   if (IsEmpty()) \
00088         return NULL; \
00089   else \
00090   { \
00091         Lock(); \
00092         int oldTail = qTail++; \
00093         if ( qTail == Length ) \
00094           qTail = 0; \
00095         TYPE *item = ( TYPE * ) Content [ oldTail ]; \
00096         Unlock(); \
00097         return item; \
00098   } \
00099 } \
00100 void NAME::Clear() \
00101 { \
00102   TYPE *item; \
00103   while (( item = Get()) != NULL ) \
00104         { delete item; } \
00105 } \
00106 void NAME::Resize ( int len ) \
00107 { \
00108   if ( len <= 0 ) \
00109         len = DEF_QUEUE_LENGTH; \
00110   if ( len == Length ) \
00111         return; \
00112   Lock(); \
00113   volatile TYPE **oldQueue = Content; \
00114   Content = ( volatile TYPE **) new TYPE *[len]; \
00115   int oldHead = qHead, oldTail = qTail; \
00116   qHead = qTail = 0; \
00117   int oldLength = Length; \
00118   Length = len; \
00119   if ( oldQueue ) \
00120   { while (( oldTail != oldHead ) && ( qHead < Length - 1 )) \
00121         { Content [ qHead++ ] = oldQueue [ oldTail++ ]; \
00122           if ( oldTail == oldLength ) \
00123                 oldTail = 0; \
00124         } \
00125   } \
00126   delete[] oldQueue; \
00127   Unlock(); \
00128 }
00129 
00130 #endif // __CSQUEUE_H__
00131 

Generated for Crystal Space by doxygen 1.2.5 written by Dimitri van Heesch, ©1997-2000