Panda3D
circBuffer.I
1 // Filename: circBuffer.I
2 // Created by: drose (08Feb99)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "pandabase.h"
16 #include "config_express.h"
17 #include "pnotify.h"
18 
19 ////////////////////////////////////////////////////////////////////
20 // Function: CircBuffer::Constructor
21 // Access: Public
22 // Description:
23 ////////////////////////////////////////////////////////////////////
24 template<class Thing, int max_size>
26 CircBuffer() {
27  _in = _out = 0;
28 }
29 
30 ////////////////////////////////////////////////////////////////////
31 // Function: CircBuffer::Destructor
32 // Access: Public
33 // Description:
34 ////////////////////////////////////////////////////////////////////
35 template<class Thing, int max_size>
37 ~CircBuffer() {
38 }
39 
40 ////////////////////////////////////////////////////////////////////
41 // Function: CircBuffer::size
42 // Access: Public
43 // Description: Returns the number of items currently in the buffer.
44 // This can safely be called without synchronization
45 // from either the reader or the writer thread, but the
46 // size may of course vary without warning after the
47 // call.
48 ////////////////////////////////////////////////////////////////////
49 template<class Thing, int max_size>
51 size() const {
52  int diff = _in - _out;
53  return (diff >= 0) ? diff : max_size + 1 + diff;
54 }
55 
56 ////////////////////////////////////////////////////////////////////
57 // Function: CircBuffer::empty
58 // Access: Public
59 // Description: Returns true if the buffer is empty. It is safe to
60 // call this without synchronization primitives from
61 // either the reader or the writer thread, but the
62 // result may vary without warning after the call.
63 ////////////////////////////////////////////////////////////////////
64 template<class Thing, int max_size>
66 empty() const {
67  return _in == _out;
68 }
69 
70 ////////////////////////////////////////////////////////////////////
71 // Function: CircBuffer::full
72 // Access: Public
73 // Description: Returns true if the buffer is full; if this is true,
74 // push_back() will fail. It is safe to call this
75 // without synchronization primitives from either the
76 // reader or the writer thread, but the result may vary
77 // without warning after the call.
78 ////////////////////////////////////////////////////////////////////
79 template<class Thing, int max_size>
81 full() const {
82  // return _in == _out-1 || (_in==max_size && _out==0);
83  return ((_in + 1) % (max_size + 1)) == _out;
84 }
85 
86 ////////////////////////////////////////////////////////////////////
87 // Function: CircBuffer::front
88 // Access: Public
89 // Description: Returns a reference to the first item in the queue.
90 // It is invalid to call this if empty() is true. It is
91 // safe to call this without synchronization only from
92 // the reading thread: the thread that calls pop_front().
93 ////////////////////////////////////////////////////////////////////
94 template<class Thing, int max_size>
95 INLINE const Thing &CircBuffer<Thing, max_size>::
96 front() const {
97  nassertr(!empty(), _array[0]);
98  return _array[_out];
99 }
100 
101 ////////////////////////////////////////////////////////////////////
102 // Function: CircBuffer::front
103 // Access: Public
104 // Description: Returns a reference to the first item in the queue.
105 // It is invalid to call this if empty() is true. It is
106 // safe to call this without synchronization only from
107 // the reading thread: the thread that calls pop_front().
108 ////////////////////////////////////////////////////////////////////
109 template<class Thing, int max_size>
110 INLINE Thing &CircBuffer<Thing, max_size>::
111 front() {
112  nassertr(!empty(), _array[0]);
113  return _array[_out];
114 }
115 
116 ////////////////////////////////////////////////////////////////////
117 // Function: CircBuffer::operator []
118 // Access: Public
119 // Description: Returns the nth element in the buffer. It is safe to
120 // call this without synchronization only from the
121 // reading thread: the thread that calls pop_front().
122 ////////////////////////////////////////////////////////////////////
123 template<class Thing, int max_size>
124 INLINE const Thing &CircBuffer<Thing, max_size>::
125 operator[] (int n) const {
126  nassertr(!empty(), _array[0]);
127  return _array[(_out + n) % (max_size + 1)];
128 }
129 
130 ////////////////////////////////////////////////////////////////////
131 // Function: CircBuffer::operator []
132 // Access: Public
133 // Description: Returns the nth element in the buffer. It is safe to
134 // call this without synchronization only from the
135 // reading thread: the thread that calls pop_front().
136 ////////////////////////////////////////////////////////////////////
137 template<class Thing, int max_size>
138 INLINE Thing &CircBuffer<Thing, max_size>::
139 operator[] (int n) {
140  nassertr(!empty(), _array[0]);
141  return _array[(_out + n) % (max_size + 1)];
142 }
143 
144 
145 ////////////////////////////////////////////////////////////////////
146 // Function: CircBuffer::pop_front
147 // Access: Public
148 // Description: Removes the first item from the buffer.
149 ////////////////////////////////////////////////////////////////////
150 template<class Thing, int max_size>
153  nassertv(!empty());
154 
155  // We need to clear out the old element to force its destructor to
156  // be called; it might be important. This will generate yet another
157  // UMR warning in Purify if the default constructor doesn't fully
158  // initialize the class.
159  _array[_out] = Thing();
160 
161  _out = (_out+1)%(max_size+1);
162 }
163 
164 
165 
166 
167 ////////////////////////////////////////////////////////////////////
168 // Function: CircBuffer::back
169 // Access: Public
170 // Description: Returns a reference to the last item in the queue.
171 // It is invalid to call this if empty() is true. It is
172 // safe to call this without synchronization primitives
173 // only from the writing thread: the thread that calls
174 // push_back().
175 ////////////////////////////////////////////////////////////////////
176 template<class Thing, int max_size>
177 INLINE const Thing &CircBuffer<Thing, max_size>::
178 back() const {
179  nassertr(!empty(), _array[0]);
180  return _array[(_in + max_size) % (max_size + 1)];
181 }
182 
183 ////////////////////////////////////////////////////////////////////
184 // Function: CircBuffer::back
185 // Access: Public
186 // Description: Returns a reference to the last item in the queue.
187 // It is invalid to call this if empty() is true. It is
188 // safe to call this without synchronization primitives
189 // only from the writing thread: the thread that calls
190 // push_back().
191 ////////////////////////////////////////////////////////////////////
192 template<class Thing, int max_size>
193 INLINE Thing &CircBuffer<Thing, max_size>::
194 back() {
195  nassertr(!empty(), _array[0]);
196  return _array[(_in + max_size) % (max_size + 1)];
197 }
198 
199 ////////////////////////////////////////////////////////////////////
200 // Function: CircBuffer::push_back
201 // Access: Public
202 // Description: Adds an item to the end of the buffer. This may fail
203 // if full() is true.
204 ////////////////////////////////////////////////////////////////////
205 template<class Thing, int max_size>
207 push_back(const Thing &t) {
208  if (full()) {
209  express_cat.error()
210  << "Circular buffer is full; cannot add requests.\n";
211  } else {
212  _array[_in] = t;
213  _in = (_in+1)%(max_size+1);
214  }
215 }
216 
217 ////////////////////////////////////////////////////////////////////
218 // Function: CircBuffer::clear
219 // Access: Public
220 // Description: Removes all items from the queue.
221 ////////////////////////////////////////////////////////////////////
222 template<class Thing, int max_size>
224 clear() {
225  _in = _out = 0;
226 }
void push_back(const Thing &t)
Adds an item to the end of the buffer.
Definition: circBuffer.I:207
bool empty() const
Returns true if the buffer is empty.
Definition: circBuffer.I:66
const Thing & back() const
Returns a reference to the last item in the queue.
Definition: circBuffer.I:178
int size() const
Returns the number of items currently in the buffer.
Definition: circBuffer.I:51
bool full() const
Returns true if the buffer is full; if this is true, push_back() will fail.
Definition: circBuffer.I:81
void clear()
Removes all items from the queue.
Definition: circBuffer.I:224
void pop_front()
Removes the first item from the buffer.
Definition: circBuffer.I:152
This class implements a queue of some type via a circular buffer.
Definition: circBuffer.h:31
const Thing & operator[](int n) const
Returns the nth element in the buffer.
Definition: circBuffer.I:125
const Thing & front() const
Returns a reference to the first item in the queue.
Definition: circBuffer.I:96