00001 // Filename: circBuffer.I 00002 // Created by: drose (08Feb99) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include <pandabase.h> 00020 00021 #include "config_express.h" 00022 00023 #include <notify.h> 00024 00025 //////////////////////////////////////////////////////////////////// 00026 // Function: CircBuffer::Constructor 00027 // Access: Public 00028 // Description: 00029 //////////////////////////////////////////////////////////////////// 00030 template<class Thing, int max_size> 00031 INLINE CircBuffer<Thing, max_size>:: 00032 CircBuffer() { 00033 _in = _out = 0; 00034 } 00035 00036 //////////////////////////////////////////////////////////////////// 00037 // Function: CircBuffer::Destructor 00038 // Access: Public 00039 // Description: 00040 //////////////////////////////////////////////////////////////////// 00041 template<class Thing, int max_size> 00042 INLINE CircBuffer<Thing, max_size>:: 00043 ~CircBuffer() { 00044 } 00045 00046 //////////////////////////////////////////////////////////////////// 00047 // Function: CircBuffer::size 00048 // Access: Public 00049 // Description: Returns the number of items currently in the buffer. 00050 // This can safely be called without synchronization 00051 // from either the reader or the writer thread, but the 00052 // size may of course vary without warning after the 00053 // call. 00054 //////////////////////////////////////////////////////////////////// 00055 template<class Thing, int max_size> 00056 INLINE int CircBuffer<Thing, max_size>:: 00057 size() const { 00058 int diff = _in - _out; 00059 return (diff >= 0) ? diff : max_size + 1 + diff; 00060 } 00061 00062 //////////////////////////////////////////////////////////////////// 00063 // Function: CircBuffer::empty 00064 // Access: Public 00065 // Description: Returns true if the buffer is empty. It is safe to 00066 // call this without synchronization primitives from 00067 // either the reader or the writer thread, but the 00068 // result may vary without warning after the call. 00069 //////////////////////////////////////////////////////////////////// 00070 template<class Thing, int max_size> 00071 INLINE bool CircBuffer<Thing, max_size>:: 00072 empty() const { 00073 return _in == _out; 00074 } 00075 00076 //////////////////////////////////////////////////////////////////// 00077 // Function: CircBuffer::full 00078 // Access: Public 00079 // Description: Returns true if the buffer is full; if this is true, 00080 // push_back() will fail. It is safe to call this 00081 // without synchronization primitives from either the 00082 // reader or the writer thread, but the result may vary 00083 // without warning after the call. 00084 //////////////////////////////////////////////////////////////////// 00085 template<class Thing, int max_size> 00086 INLINE bool CircBuffer<Thing, max_size>:: 00087 full() const { 00088 // return _in == _out-1 || (_in==max_size && _out==0); 00089 return ((_in + 1) % (max_size + 1)) == _out; 00090 } 00091 00092 //////////////////////////////////////////////////////////////////// 00093 // Function: CircBuffer::front 00094 // Access: Public 00095 // Description: Returns a reference to the first item in the queue. 00096 // It is invalid to call this if empty() is true. It is 00097 // safe to call this without synchronization only from 00098 // the reading thread: the thread that calls pop_front(). 00099 //////////////////////////////////////////////////////////////////// 00100 template<class Thing, int max_size> 00101 INLINE const Thing &CircBuffer<Thing, max_size>:: 00102 front() const { 00103 nassertr(!empty(), _array[0]); 00104 return _array[_out]; 00105 } 00106 00107 //////////////////////////////////////////////////////////////////// 00108 // Function: CircBuffer::front 00109 // Access: Public 00110 // Description: Returns a reference to the first item in the queue. 00111 // It is invalid to call this if empty() is true. It is 00112 // safe to call this without synchronization only from 00113 // the reading thread: the thread that calls pop_front(). 00114 //////////////////////////////////////////////////////////////////// 00115 template<class Thing, int max_size> 00116 INLINE Thing &CircBuffer<Thing, max_size>:: 00117 front() { 00118 nassertr(!empty(), _array[0]); 00119 return _array[_out]; 00120 } 00121 00122 //////////////////////////////////////////////////////////////////// 00123 // Function: CircBuffer::operator [] 00124 // Access: Public 00125 // Description: Returns the nth element in the buffer. It is safe to 00126 // call this without synchronization only from the 00127 // reading thread: the thread that calls pop_front(). 00128 //////////////////////////////////////////////////////////////////// 00129 template<class Thing, int max_size> 00130 INLINE const Thing &CircBuffer<Thing, max_size>:: 00131 operator[] (int n) const { 00132 nassertr(!empty(), _array[0]); 00133 return _array[(_out + n) % (max_size + 1)]; 00134 } 00135 00136 //////////////////////////////////////////////////////////////////// 00137 // Function: CircBuffer::operator [] 00138 // Access: Public 00139 // Description: Returns the nth element in the buffer. It is safe to 00140 // call this without synchronization only from the 00141 // reading thread: the thread that calls pop_front(). 00142 //////////////////////////////////////////////////////////////////// 00143 template<class Thing, int max_size> 00144 INLINE Thing &CircBuffer<Thing, max_size>:: 00145 operator[] (int n) { 00146 nassertr(!empty(), _array[0]); 00147 return _array[(_out + n) % (max_size + 1)]; 00148 } 00149 00150 00151 //////////////////////////////////////////////////////////////////// 00152 // Function: CircBuffer::pop_front 00153 // Access: Public 00154 // Description: Removes the first item from the buffer. 00155 //////////////////////////////////////////////////////////////////// 00156 template<class Thing, int max_size> 00157 INLINE void CircBuffer<Thing, max_size>:: 00158 pop_front() { 00159 nassertv(!empty()); 00160 00161 // We need to clear out the old element to force its destructor to 00162 // be called; it might be important. This will generate yet another 00163 // UMR warning in Purify if the default constructor doesn't fully 00164 // initialize the class. 00165 _array[_out] = Thing(); 00166 00167 _out = (_out+1)%(max_size+1); 00168 } 00169 00170 00171 00172 00173 //////////////////////////////////////////////////////////////////// 00174 // Function: CircBuffer::back 00175 // Access: Public 00176 // Description: Returns a reference to the last item in the queue. 00177 // It is invalid to call this if empty() is true. It is 00178 // safe to call this without synchronization primitives 00179 // only from the writing thread: the thread that calls 00180 // push_back(). 00181 //////////////////////////////////////////////////////////////////// 00182 template<class Thing, int max_size> 00183 INLINE const Thing &CircBuffer<Thing, max_size>:: 00184 back() const { 00185 nassertr(!empty(), _array[0]); 00186 return _array[(_in + max_size) % (max_size + 1)]; 00187 } 00188 00189 //////////////////////////////////////////////////////////////////// 00190 // Function: CircBuffer::back 00191 // Access: Public 00192 // Description: Returns a reference to the last item in the queue. 00193 // It is invalid to call this if empty() is true. It is 00194 // safe to call this without synchronization primitives 00195 // only from the writing thread: the thread that calls 00196 // push_back(). 00197 //////////////////////////////////////////////////////////////////// 00198 template<class Thing, int max_size> 00199 INLINE Thing &CircBuffer<Thing, max_size>:: 00200 back() { 00201 nassertr(!empty(), _array[0]); 00202 return _array[(_in + max_size) % (max_size + 1)]; 00203 } 00204 00205 //////////////////////////////////////////////////////////////////// 00206 // Function: CircBuffer::push_back 00207 // Access: Public 00208 // Description: Adds an item to the end of the buffer. This may fail 00209 // if full() is true. 00210 //////////////////////////////////////////////////////////////////// 00211 template<class Thing, int max_size> 00212 INLINE void CircBuffer<Thing, max_size>:: 00213 push_back(const Thing &t) { 00214 if (full()) { 00215 express_cat.error() 00216 << "Circular buffer is full; cannot add requests.\n"; 00217 } else { 00218 _array[_in] = t; 00219 _in = (_in+1)%(max_size+1); 00220 } 00221 }