Panda3D
Loading...
Searching...
No Matches
updateSeq.I
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file updateSeq.I
10 * @author drose
11 * @date 1999-09-30
12 */
13
14/**
15 * Creates an UpdateSeq in the given state.
16 */
17constexpr UpdateSeq::
18UpdateSeq(unsigned int seq) : _seq(seq) {
19}
20
21/**
22 * Creates an UpdateSeq in the 'initial' state.
23 */
24constexpr UpdateSeq::
25UpdateSeq() : _seq((unsigned int)SC_initial) {
26}
27
28/**
29 *
30 */
31INLINE UpdateSeq::
32UpdateSeq(const UpdateSeq &copy) : _seq(AtomicAdjust::get(copy._seq)) {
33}
34
35/**
36 *
37 */
38constexpr UpdateSeq::
39UpdateSeq(const UpdateSeq &&from) noexcept : _seq(from._seq) {
40}
41
42/**
43 *
44 */
45INLINE UpdateSeq &UpdateSeq::
46operator = (const UpdateSeq &copy) {
47 AtomicAdjust::set(_seq, AtomicAdjust::get(copy._seq));
48 return *this;
49}
50
51/**
52 * Resets the UpdateSeq to the 'initial' state.
53 */
54INLINE void UpdateSeq::
55clear() {
56 AtomicAdjust::set(_seq, (AtomicAdjust::Integer)SC_initial);
57}
58
59/**
60 * Returns true if the UpdateSeq is in the 'initial' state.
61 */
62INLINE bool UpdateSeq::
63is_initial() const {
64 return AtomicAdjust::get(_seq) == (AtomicAdjust::Integer)SC_initial;
65}
66
67/**
68 * Returns true if the UpdateSeq is in the 'old' state.
69 */
70INLINE bool UpdateSeq::
71is_old() const {
72 return AtomicAdjust::get(_seq) == (AtomicAdjust::Integer)SC_old;
73}
74
75/**
76 * Returns true if the UpdateSeq is in the 'fresh' state.
77 */
78INLINE bool UpdateSeq::
79is_fresh() const {
80 return AtomicAdjust::get(_seq) == (AtomicAdjust::Integer)SC_fresh;
81}
82
83/**
84 * Returns true if the UpdateSeq is in any special states, i.e. 'initial',
85 * 'old', or 'fresh'.
86 */
87INLINE bool UpdateSeq::
88is_special() const {
89 // This relies on the assumption that (~0 + 1) == 0.
90 return (((unsigned int)AtomicAdjust::get(_seq) + 1u) <= 2u);
91}
92
93/**
94 *
95 */
96INLINE bool UpdateSeq::
97operator == (const UpdateSeq &other) const {
98 return AtomicAdjust::get(_seq) == AtomicAdjust::get(other._seq);
99}
100
101/**
102 *
103 */
104INLINE bool UpdateSeq::
105operator != (const UpdateSeq &other) const {
106 return AtomicAdjust::get(_seq) != AtomicAdjust::get(other._seq);
107}
108
109/**
110 *
111 */
112INLINE bool UpdateSeq::
113operator < (const UpdateSeq &other) const {
114 return priv_lt(AtomicAdjust::get(_seq), AtomicAdjust::get(other._seq));
115}
116
117/**
118 *
119 */
120INLINE bool UpdateSeq::
121operator <= (const UpdateSeq &other) const {
122 return priv_le(AtomicAdjust::get(_seq), AtomicAdjust::get(other._seq));
123}
124
125/**
126 *
127 */
128INLINE bool UpdateSeq::
129operator > (const UpdateSeq &other) const {
130 return (other < (*this));
131}
132
133/**
134 *
135 */
136INLINE bool UpdateSeq::
137operator >= (const UpdateSeq &other) const {
138 return (other <= (*this));
139}
140
141/**
142 *
143 */
144INLINE UpdateSeq UpdateSeq::
145operator ++ () {
146 AtomicAdjust::Integer old_seq = AtomicAdjust::get(_seq);
147 AtomicAdjust::Integer new_seq = old_seq + 1;
148 if (priv_is_special(new_seq)) {
149 // Oops, wraparound. We don't want to confuse the new value with our
150 // special cases.
151 new_seq = (AtomicAdjust::Integer)SC_old + 1;
152 }
153
154#ifdef HAVE_THREADS
155 AtomicAdjust::Integer result = AtomicAdjust::compare_and_exchange(_seq, old_seq, new_seq);
156 while (result != old_seq) {
157 // Some other thread beat us to it; try again.
158 old_seq = AtomicAdjust::get(_seq);
159 new_seq = old_seq + 1;
160 if (priv_is_special(new_seq)) {
161 // Oops, wraparound. We don't want to confuse the new value with our
162 // special cases.
163 new_seq = (AtomicAdjust::Integer)SC_old + 1;
164 }
165 result = AtomicAdjust::compare_and_exchange(_seq, old_seq, new_seq);
166 }
167#else
168 _seq = new_seq;
169#endif // HAVE_THREADS
170
171 return *this;
172}
173
174/**
175 *
176 */
177INLINE UpdateSeq UpdateSeq::
178operator ++ (int) {
179 AtomicAdjust::Integer old_seq = AtomicAdjust::get(_seq);
180 AtomicAdjust::Integer new_seq = old_seq + 1;
181 if (priv_is_special(new_seq)) {
182 // Oops, wraparound. We don't want to confuse the new value with our
183 // special cases.
184 new_seq = (AtomicAdjust::Integer)SC_old + 1;
185 }
186
187#ifdef HAVE_THREADS
188 AtomicAdjust::Integer result = AtomicAdjust::compare_and_exchange(_seq, old_seq, new_seq);
189 while (result != old_seq) {
190 // Some other thread beat us to it; try again.
191 old_seq = AtomicAdjust::get(_seq);
192 new_seq = old_seq + 1;
193 if (priv_is_special(new_seq)) {
194 // Oops, wraparound. We don't want to confuse the new value with our
195 // special cases.
196 new_seq = (AtomicAdjust::Integer)SC_old + 1;
197 }
198 result = AtomicAdjust::compare_and_exchange(_seq, old_seq, new_seq);
199 }
200#else
201 _seq = new_seq;
202#endif // HAVE_THREADS
203
204 UpdateSeq temp;
205 temp._seq = old_seq;
206 return temp;
207}
208
209/**
210 * Returns the internal integer value associated with the UpdateSeq. Useful
211 * for debugging only.
212 */
213INLINE AtomicAdjust::Integer UpdateSeq::
214get_seq() const {
215 return _seq;
216}
217
218/**
219 *
220 */
221INLINE void UpdateSeq::
222output(std::ostream &out) const {
223 AtomicAdjust::Integer seq = AtomicAdjust::get(_seq);
224 switch (seq) {
225 case (AtomicAdjust::Integer)SC_initial:
226 out << "initial";
227 break;
228
229 case (AtomicAdjust::Integer)SC_old:
230 out << "old";
231 break;
232
233 case (AtomicAdjust::Integer)SC_fresh:
234 out << "fresh";
235 break;
236
237 default:
238 out << (int)seq;
239 }
240}
241
242/**
243 * The private implementation of is_special().
244 */
245INLINE bool UpdateSeq::
246priv_is_special(AtomicAdjust::Integer seq) {
247 // This relies on the assumption that (~0 + 1) == 0.
248 return (((unsigned int)seq + 1) <= 2);
249}
250
251/**
252 * The private implementation of operator < ().
253 */
254INLINE bool UpdateSeq::
255priv_lt(AtomicAdjust::Integer a, AtomicAdjust::Integer b) {
256 // The special cases of SC_initial or SC_old are less than all other non-
257 // special numbers, and SC_initial is less than SC_old. The special case of
258 // SC_fresh is greater than all other non-special numbers. For all other
259 // cases, we use a circular comparision such that n < m iff (signed)(n - m)
260 // < 0.
261 return
262 (priv_is_special(a) || priv_is_special(b)) ? ((unsigned int)a < (unsigned int)b) :
263 ((signed int)(a - b) < 0);
264}
265
266/**
267 * The private implementation of operator <= ().
268 */
269INLINE bool UpdateSeq::
270priv_le(AtomicAdjust::Integer a, AtomicAdjust::Integer b) {
271 return (a == b) || priv_lt(a, b);
272}
273
274INLINE std::ostream &operator << (std::ostream &out, const UpdateSeq &value) {
275 value.output(out);
276 return out;
277}
A trivial implementation for atomic adjustments for systems that don't require multiprogramming,...
static Integer set(Integer &var, Integer new_value)
Atomically changes the indicated variable and returns the original value.
static Integer compare_and_exchange(Integer &mem, Integer old_value, Integer new_value)
Atomic compare and exchange.
static Integer get(const Integer &var)
Atomically retrieves the snapshot value of the indicated variable.
This is a sequence number that increments monotonically.
Definition updateSeq.h:37
constexpr UpdateSeq()
Creates an UpdateSeq in the 'initial' state.
Definition updateSeq.I:25
void clear()
Resets the UpdateSeq to the 'initial' state.
Definition updateSeq.I:55
get_seq
Returns the internal integer value associated with the UpdateSeq.
Definition updateSeq.h:69
bool is_old() const
Returns true if the UpdateSeq is in the 'old' state.
Definition updateSeq.I:71
bool is_initial() const
Returns true if the UpdateSeq is in the 'initial' state.
Definition updateSeq.I:63
bool is_fresh() const
Returns true if the UpdateSeq is in the 'fresh' state.
Definition updateSeq.I:79
bool is_special() const
Returns true if the UpdateSeq is in any special states, i.e.
Definition updateSeq.I:88