Panda3D
 All Classes Functions Variables Enumerations
atomicAdjustWin32Impl.I
1 // Filename: atomicAdjustWin32Impl.I
2 // Created by: drose (07Feb06)
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: AtomicAdjustWin32Impl::inc
18 // Access: Public, Static
19 // Description: Atomically increments the indicated variable.
20 ////////////////////////////////////////////////////////////////////
21 INLINE void AtomicAdjustWin32Impl::
22 inc(TVOLATILE AtomicAdjustWin32Impl::Integer &var) {
23  assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0);
24 #ifdef _WIN64
25  InterlockedIncrement64(&var);
26 #else
27  InterlockedIncrement(&var);
28 #endif // _WIN64
29 }
30 
31 ////////////////////////////////////////////////////////////////////
32 // Function: AtomicAdjustWin32Impl::dec
33 // Access: Public, Static
34 // Description: Atomically decrements the indicated variable and
35 // returns true if the new value is nonzero, false if it
36 // is zero.
37 ////////////////////////////////////////////////////////////////////
38 INLINE bool AtomicAdjustWin32Impl::
39 dec(TVOLATILE AtomicAdjustWin32Impl::Integer &var) {
40  assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0);
41 #ifdef _WIN64
42  return (InterlockedDecrement64(&var) != 0);
43 #else
44  return (InterlockedDecrement(&var) != 0);
45 #endif // _WIN64
46 }
47 
48 ////////////////////////////////////////////////////////////////////
49 // Function: AtomicAdjustWin32Impl::add
50 // Access: Public, Static
51 // Description: Atomically computes var += delta. It is legal for
52 // delta to be negative.
53 ////////////////////////////////////////////////////////////////////
54 INLINE void AtomicAdjustWin32Impl::
55 add(TVOLATILE AtomicAdjustWin32Impl::Integer &var, AtomicAdjustWin32Impl::Integer delta) {
56  assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0);
57 #ifdef _WIN64
58  InterlockedAdd64(&var, delta);
59 #else
60  AtomicAdjustWin32Impl::Integer orig_value = var;
61  while (compare_and_exchange(var, orig_value, orig_value + delta) != orig_value) {
62  orig_value = var;
63  }
64 #endif // _WIN64
65 }
66 
67 ////////////////////////////////////////////////////////////////////
68 // Function: AtomicAdjustWin32Impl::set
69 // Access: Public, Static
70 // Description: Atomically changes the indicated variable and
71 // returns the original value.
72 ////////////////////////////////////////////////////////////////////
73 INLINE AtomicAdjustWin32Impl::Integer AtomicAdjustWin32Impl::
74 set(TVOLATILE AtomicAdjustWin32Impl::Integer &var,
75  AtomicAdjustWin32Impl::Integer new_value) {
76  assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0);
77 #ifdef _WIN64
78  return InterlockedExchange64(&var, new_value);
79 #else
80  return InterlockedExchange(&var, new_value);
81 #endif // _WIN64
82 }
83 
84 ////////////////////////////////////////////////////////////////////
85 // Function: AtomicAdjustWin32Impl::get
86 // Access: Public, Static
87 // Description: Atomically retrieves the snapshot value of the
88 // indicated variable. This is the only guaranteed safe
89 // way to retrieve the value that other threads might be
90 // asynchronously setting, incrementing, or decrementing
91 // (via other AtomicAjust methods).
92 ////////////////////////////////////////////////////////////////////
93 INLINE AtomicAdjustWin32Impl::Integer AtomicAdjustWin32Impl::
94 get(const TVOLATILE AtomicAdjustWin32Impl::Integer &var) {
95  // On Intel platforms, word-aligned loads are atomic (if performed
96  // in a single instruction). We can't guarantee the compiler will
97  // generate a single instruction to load this value, but it
98  // certainly won't happen if its address isn't word-aligned, so make
99  // sure that's the case.
100  assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0);
101  return var;
102 }
103 
104 ////////////////////////////////////////////////////////////////////
105 // Function: AtomicAdjustWin32Impl::set_ptr
106 // Access: Public, Static
107 // Description: Atomically changes the indicated variable and
108 // returns the original value.
109 ////////////////////////////////////////////////////////////////////
110 INLINE AtomicAdjustWin32Impl::Pointer AtomicAdjustWin32Impl::
111 set_ptr(TVOLATILE AtomicAdjustWin32Impl::Pointer &var,
112  AtomicAdjustWin32Impl::Pointer new_value) {
113  assert((((size_t)&var) & (sizeof(Pointer) - 1)) == 0);
114  return InterlockedExchangePointer(&var, new_value);
115 }
116 
117 ////////////////////////////////////////////////////////////////////
118 // Function: AtomicAdjustWin32Impl::get_ptr
119 // Access: Public, Static
120 // Description: Atomically retrieves the snapshot value of the
121 // indicated variable. This is the only guaranteed safe
122 // way to retrieve the value that other threads might be
123 // asynchronously setting, incrementing, or decrementing
124 // (via other AtomicAjust methods).
125 ////////////////////////////////////////////////////////////////////
126 INLINE AtomicAdjustWin32Impl::Pointer AtomicAdjustWin32Impl::
127 get_ptr(const TVOLATILE AtomicAdjustWin32Impl::Pointer &var) {
128  // As in get(), make sure the address is word-aligned.
129  assert((((size_t)&var) & (sizeof(Pointer) - 1)) == 0);
130  return var;
131 }
132 
133 ////////////////////////////////////////////////////////////////////
134 // Function: AtomicAdjustWin32Impl::compare_and_exchange
135 // Access: Public, Static
136 // Description: Atomic compare and exchange.
137 //
138 // If mem is equal to old_value, store new_value in mem.
139 // In either case, return the original value of mem.
140 // The caller can test for success by comparing
141 // return_value == old_value.
142 //
143 // The atomic function expressed in pseudo-code:
144 //
145 // orig_value = mem;
146 // if (mem == old_value) {
147 // mem = new_value;
148 // }
149 // return orig_value;
150 //
151 ////////////////////////////////////////////////////////////////////
152 INLINE AtomicAdjustWin32Impl::Integer AtomicAdjustWin32Impl::
153 compare_and_exchange(TVOLATILE AtomicAdjustWin32Impl::Integer &mem,
154  AtomicAdjustWin32Impl::Integer old_value,
155  AtomicAdjustWin32Impl::Integer new_value) {
156  assert((((size_t)&mem) & (sizeof(Integer) - 1)) == 0);
157  // Note that the AtomicAdjust parameter order is different from
158  // Windows convention!
159 #ifdef _WIN64
160  return InterlockedCompareExchange64((TVOLATILE LONGLONG *)&mem, new_value, old_value);
161 #else
162  return InterlockedCompareExchange((TVOLATILE LONG *)&mem, new_value, old_value);
163 #endif // _WIN64
164 }
165 
166 ////////////////////////////////////////////////////////////////////
167 // Function: AtomicAdjustWin32Impl::compare_and_exchange_ptr
168 // Access: Public, Static
169 // Description: Atomic compare and exchange.
170 //
171 // As above, but works on pointers instead of integers.
172 ////////////////////////////////////////////////////////////////////
173 INLINE AtomicAdjustWin32Impl::Pointer AtomicAdjustWin32Impl::
174 compare_and_exchange_ptr(TVOLATILE AtomicAdjustWin32Impl::Pointer &mem,
175  AtomicAdjustWin32Impl::Pointer old_value,
176  AtomicAdjustWin32Impl::Pointer new_value) {
177  assert((((size_t)&mem) & (sizeof(Pointer) - 1)) == 0);
178  // Note that the AtomicAdjust parameter order is different from
179  // Windows convention!
180  return InterlockedCompareExchangePointer(&mem, new_value, old_value);
181 }