|
csqueue.h00001 /* 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 |