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