Panda3D
 All Classes Functions Variables Enumerations
circBuffer.I
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 }
 All Classes Functions Variables Enumerations