Panda3D
updateSeq.I
1 // Filename: updateSeq.I
2 // Created by: drose (30Sep99)
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 
16 ////////////////////////////////////////////////////////////////////
17 // Function: UpdateSeq::Default Constructor
18 // Access: Published
19 // Description: Creates an UpdateSeq in the 'initial' state.
20 ////////////////////////////////////////////////////////////////////
21 INLINE UpdateSeq::
23  _seq = (unsigned int)SC_initial;
24 }
25 
26 ////////////////////////////////////////////////////////////////////
27 // Function: UpdateSeq::initial (named constructor)
28 // Access: Published, Static
29 // Description: Returns an UpdateSeq in the 'initial' state.
30 ////////////////////////////////////////////////////////////////////
33  return UpdateSeq();
34 }
35 
36 ////////////////////////////////////////////////////////////////////
37 // Function: UpdateSeq::old (named constructor)
38 // Access: Published, Static
39 // Description: Returns an UpdateSeq in the 'old' state.
40 ////////////////////////////////////////////////////////////////////
42 old() {
43  UpdateSeq result;
44  result._seq = (unsigned int)SC_old;
45  return result;
46 }
47 
48 ////////////////////////////////////////////////////////////////////
49 // Function: UpdateSeq::fresh (named constructor)
50 // Access: Published, Static
51 // Description: Returns an UpdateSeq in the 'fresh' state.
52 ////////////////////////////////////////////////////////////////////
54 fresh() {
55  UpdateSeq result;
56  result._seq = (unsigned int)SC_fresh;
57  return result;
58 }
59 
60 ////////////////////////////////////////////////////////////////////
61 // Function: UpdateSeq::Copy Constructor
62 // Access: Published
63 // Description:
64 ////////////////////////////////////////////////////////////////////
65 INLINE UpdateSeq::
66 UpdateSeq(const UpdateSeq &copy) {
67  _seq = AtomicAdjust::get(copy._seq);
68 }
69 
70 ////////////////////////////////////////////////////////////////////
71 // Function: UpdateSeq::Copy Assignment operator
72 // Access: Published
73 // Description:
74 ////////////////////////////////////////////////////////////////////
75 INLINE UpdateSeq &UpdateSeq::
76 operator = (const UpdateSeq &copy) {
77  AtomicAdjust::set(_seq, AtomicAdjust::get(copy._seq));
78  return *this;
79 }
80 
81 ////////////////////////////////////////////////////////////////////
82 // Function: UpdateSeq::clear
83 // Access: Published
84 // Description: Resets the UpdateSeq to the 'initial' state.
85 ////////////////////////////////////////////////////////////////////
86 INLINE void UpdateSeq::
87 clear() {
88  AtomicAdjust::set(_seq, (AtomicAdjust::Integer)SC_initial);
89 }
90 
91 ////////////////////////////////////////////////////////////////////
92 // Function: UpdateSeq::is_initial
93 // Access: Published
94 // Description: Returns true if the UpdateSeq is in the 'initial'
95 // state.
96 ////////////////////////////////////////////////////////////////////
97 INLINE bool UpdateSeq::
98 is_initial() const {
99  return AtomicAdjust::get(_seq) == (AtomicAdjust::Integer)SC_initial;
100 }
101 
102 ////////////////////////////////////////////////////////////////////
103 // Function: UpdateSeq::is_old
104 // Access: Published
105 // Description: Returns true if the UpdateSeq is in the 'old' state.
106 ////////////////////////////////////////////////////////////////////
107 INLINE bool UpdateSeq::
108 is_old() const {
109  return AtomicAdjust::get(_seq) == (AtomicAdjust::Integer)SC_old;
110 }
111 
112 ////////////////////////////////////////////////////////////////////
113 // Function: UpdateSeq::is_fresh
114 // Access: Published
115 // Description: Returns true if the UpdateSeq is in the 'fresh'
116 // state.
117 ////////////////////////////////////////////////////////////////////
118 INLINE bool UpdateSeq::
119 is_fresh() const {
120  return AtomicAdjust::get(_seq) == (AtomicAdjust::Integer)SC_fresh;
121 }
122 
123 ////////////////////////////////////////////////////////////////////
124 // Function: UpdateSeq::is_special
125 // Access: Published
126 // Description: Returns true if the UpdateSeq is in any special
127 // states, i.e. 'initial', 'old', or 'fresh'.
128 ////////////////////////////////////////////////////////////////////
129 INLINE bool UpdateSeq::
130 is_special() const {
131  // This relies on the assumption that (~0 + 1) == 0.
132  return ((AtomicAdjust::get(_seq) + 1) <= 2);
133 }
134 
135 ////////////////////////////////////////////////////////////////////
136 // Function: UpdateSeq::Equality operator
137 // Access: Published
138 // Description:
139 ////////////////////////////////////////////////////////////////////
140 INLINE bool UpdateSeq::
141 operator == (const UpdateSeq &other) const {
142  return AtomicAdjust::get(_seq) == AtomicAdjust::get(other._seq);
143 }
144 
145 ////////////////////////////////////////////////////////////////////
146 // Function: UpdateSeq::Inequality operator
147 // Access: Published
148 // Description:
149 ////////////////////////////////////////////////////////////////////
150 INLINE bool UpdateSeq::
151 operator != (const UpdateSeq &other) const {
152  return AtomicAdjust::get(_seq) != AtomicAdjust::get(other._seq);
153 }
154 
155 ////////////////////////////////////////////////////////////////////
156 // Function: UpdateSeq::Comparison operator
157 // Access: Published
158 // Description:
159 ////////////////////////////////////////////////////////////////////
160 INLINE bool UpdateSeq::
161 operator < (const UpdateSeq &other) const {
162  return priv_lt(AtomicAdjust::get(_seq), AtomicAdjust::get(other._seq));
163 }
164 
165 ////////////////////////////////////////////////////////////////////
166 // Function: UpdateSeq::Comparison operator
167 // Access: Published
168 // Description:
169 ////////////////////////////////////////////////////////////////////
170 INLINE bool UpdateSeq::
171 operator <= (const UpdateSeq &other) const {
172  return priv_le(AtomicAdjust::get(_seq), AtomicAdjust::get(other._seq));
173 }
174 
175 ////////////////////////////////////////////////////////////////////
176 // Function: UpdateSeq::Comparison operator
177 // Access: Published
178 // Description:
179 ////////////////////////////////////////////////////////////////////
180 INLINE bool UpdateSeq::
181 operator > (const UpdateSeq &other) const {
182  return (other < (*this));
183 }
184 
185 ////////////////////////////////////////////////////////////////////
186 // Function: UpdateSeq::Comparison operator
187 // Access: Published
188 // Description:
189 ////////////////////////////////////////////////////////////////////
190 INLINE bool UpdateSeq::
191 operator >= (const UpdateSeq &other) const {
192  return (other <= (*this));
193 }
194 
195 ////////////////////////////////////////////////////////////////////
196 // Function: UpdateSeq::Preincrement operator
197 // Access: Published
198 // Description:
199 ////////////////////////////////////////////////////////////////////
200 INLINE UpdateSeq UpdateSeq::
201 operator ++ () {
202  AtomicAdjust::Integer old_seq = AtomicAdjust::get(_seq);
203  AtomicAdjust::Integer new_seq = old_seq + 1;
204  if (priv_is_special(new_seq)) {
205  // Oops, wraparound. We don't want to confuse the new value
206  // with our special cases.
207  new_seq = (AtomicAdjust::Integer)SC_old + 1;
208  }
209 
210 #ifdef HAVE_THREADS
211  AtomicAdjust::Integer result = AtomicAdjust::compare_and_exchange(_seq, old_seq, new_seq);
212  while (result != old_seq) {
213  // Some other thread beat us to it; try again.
214  old_seq = AtomicAdjust::get(_seq);
215  new_seq = old_seq + 1;
216  if (priv_is_special(new_seq)) {
217  // Oops, wraparound. We don't want to confuse the new value
218  // with our special cases.
219  new_seq = (AtomicAdjust::Integer)SC_old + 1;
220  }
221  result = AtomicAdjust::compare_and_exchange(_seq, old_seq, new_seq);
222  }
223 #else
224  _seq = new_seq;
225 #endif // HAVE_THREADS
226 
227  return *this;
228 }
229 
230 ////////////////////////////////////////////////////////////////////
231 // Function: UpdateSeq::Postincrement operator
232 // Access: Published
233 // Description:
234 ////////////////////////////////////////////////////////////////////
235 INLINE UpdateSeq UpdateSeq::
236 operator ++ (int) {
237  AtomicAdjust::Integer old_seq = AtomicAdjust::get(_seq);
238  AtomicAdjust::Integer new_seq = old_seq + 1;
239  if (priv_is_special(new_seq)) {
240  // Oops, wraparound. We don't want to confuse the new value
241  // with our special cases.
242  new_seq = (AtomicAdjust::Integer)SC_old + 1;
243  }
244 
245 #ifdef HAVE_THREADS
246  AtomicAdjust::Integer result = AtomicAdjust::compare_and_exchange(_seq, old_seq, new_seq);
247  while (result != old_seq) {
248  // Some other thread beat us to it; try again.
249  old_seq = AtomicAdjust::get(_seq);
250  new_seq = old_seq + 1;
251  if (priv_is_special(new_seq)) {
252  // Oops, wraparound. We don't want to confuse the new value
253  // with our special cases.
254  new_seq = (AtomicAdjust::Integer)SC_old + 1;
255  }
256  result = AtomicAdjust::compare_and_exchange(_seq, old_seq, new_seq);
257  }
258 #else
259  _seq = new_seq;
260 #endif // HAVE_THREADS
261 
262  UpdateSeq temp;
263  temp._seq = old_seq;
264  return temp;
265 }
266 
267 ////////////////////////////////////////////////////////////////////
268 // Function: UpdateSeq::get_seq
269 // Access: Published
270 // Description: Returns the internal integer value associated with
271 // the UpdateSeq. Useful for debugging only.
272 ////////////////////////////////////////////////////////////////////
273 INLINE AtomicAdjust::Integer UpdateSeq::
274 get_seq() const {
275  return _seq;
276 }
277 
278 ////////////////////////////////////////////////////////////////////
279 // Function: UpdateSeq::output
280 // Access: Published
281 // Description:
282 ////////////////////////////////////////////////////////////////////
283 INLINE void UpdateSeq::
284 output(ostream &out) const {
285  AtomicAdjust::Integer seq = AtomicAdjust::get(_seq);
286  switch (seq) {
287  case (AtomicAdjust::Integer)SC_initial:
288  out << "initial";
289  break;
290 
291  case (AtomicAdjust::Integer)SC_old:
292  out << "old";
293  break;
294 
295  case (AtomicAdjust::Integer)SC_fresh:
296  out << "fresh";
297  break;
298 
299  default:
300  out << (int)seq;
301  }
302 }
303 
304 ////////////////////////////////////////////////////////////////////
305 // Function: UpdateSeq::priv_is_special
306 // Access: Private, Static
307 // Description: The private implementation of is_special().
308 ////////////////////////////////////////////////////////////////////
309 INLINE bool UpdateSeq::
310 priv_is_special(AtomicAdjust::Integer seq) {
311  // This relies on the assumption that (~0 + 1) == 0.
312  return (((unsigned int)seq + 1) <= 2);
313 }
314 
315 ////////////////////////////////////////////////////////////////////
316 // Function: UpdateSeq::priv_lt
317 // Access: Private, Static
318 // Description: The private implementation of operator < ().
319 ////////////////////////////////////////////////////////////////////
320 INLINE bool UpdateSeq::
321 priv_lt(AtomicAdjust::Integer a, AtomicAdjust::Integer b) {
322  // The special cases of SC_initial or SC_old are less than all other
323  // non-special numbers, and SC_initial is less than SC_old. The
324  // special case of SC_fresh is greater than all other non-special
325  // numbers. For all other cases, we use a circular comparision such
326  // that n < m iff (signed)(n - m) < 0.
327  return
328  (priv_is_special(a) || priv_is_special(b)) ? ((unsigned int)a < (unsigned int)b) :
329  ((signed int)(a - b) < 0);
330 }
331 
332 ////////////////////////////////////////////////////////////////////
333 // Function: UpdateSeq::priv_le
334 // Access: Private, Static
335 // Description: The private implementation of operator <= ().
336 ////////////////////////////////////////////////////////////////////
337 INLINE bool UpdateSeq::
338 priv_le(AtomicAdjust::Integer a, AtomicAdjust::Integer b) {
339  return (a == b) || priv_lt(a, b);
340 }
341 
342 INLINE ostream &operator << (ostream &out, const UpdateSeq &value) {
343  value.output(out);
344  return out;
345 }
void clear()
Resets the UpdateSeq to the &#39;initial&#39; state.
Definition: updateSeq.I:87
static UpdateSeq fresh()
Returns an UpdateSeq in the &#39;fresh&#39; state.
Definition: updateSeq.I:54
bool is_special() const
Returns true if the UpdateSeq is in any special states, i.e.
Definition: updateSeq.I:130
bool is_initial() const
Returns true if the UpdateSeq is in the &#39;initial&#39; state.
Definition: updateSeq.I:98
UpdateSeq()
Creates an UpdateSeq in the &#39;initial&#39; state.
Definition: updateSeq.I:22
static Integer get(const Integer &var)
Atomically retrieves the snapshot value of the indicated variable.
static UpdateSeq old()
Returns an UpdateSeq in the &#39;old&#39; state.
Definition: updateSeq.I:42
bool is_fresh() const
Returns true if the UpdateSeq is in the &#39;fresh&#39; state.
Definition: updateSeq.I:119
static Integer set(Integer &var, Integer new_value)
Atomically changes the indicated variable and returns the original value.
AtomicAdjust::Integer get_seq() const
Returns the internal integer value associated with the UpdateSeq.
Definition: updateSeq.I:274
bool is_old() const
Returns true if the UpdateSeq is in the &#39;old&#39; state.
Definition: updateSeq.I:108
This is a sequence number that increments monotonically.
Definition: updateSeq.h:43
static Integer compare_and_exchange(Integer &mem, Integer old_value, Integer new_value)
Atomic compare and exchange.
static UpdateSeq initial()
Returns an UpdateSeq in the &#39;initial&#39; state.
Definition: updateSeq.I:32