00001 // Filename: atomicAdjustWin32Impl.I 00002 // Created by: drose (07Feb06) 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 00016 //////////////////////////////////////////////////////////////////// 00017 // Function: AtomicAdjustWin32Impl::inc 00018 // Access: Public, Static 00019 // Description: Atomically increments the indicated variable. 00020 //////////////////////////////////////////////////////////////////// 00021 INLINE void AtomicAdjustWin32Impl:: 00022 inc(TVOLATILE AtomicAdjustWin32Impl::Integer &var) { 00023 assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0); 00024 #ifdef _WIN64 00025 InterlockedIncrement64(&var); 00026 #else 00027 InterlockedIncrement(&var); 00028 #endif // _WIN64 00029 } 00030 00031 //////////////////////////////////////////////////////////////////// 00032 // Function: AtomicAdjustWin32Impl::dec 00033 // Access: Public, Static 00034 // Description: Atomically decrements the indicated variable and 00035 // returns true if the new value is nonzero, false if it 00036 // is zero. 00037 //////////////////////////////////////////////////////////////////// 00038 INLINE bool AtomicAdjustWin32Impl:: 00039 dec(TVOLATILE AtomicAdjustWin32Impl::Integer &var) { 00040 assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0); 00041 #ifdef _WIN64 00042 return (InterlockedDecrement64(&var) != 0); 00043 #else 00044 return (InterlockedDecrement(&var) != 0); 00045 #endif // _WIN64 00046 } 00047 00048 //////////////////////////////////////////////////////////////////// 00049 // Function: AtomicAdjustWin32Impl::add 00050 // Access: Public, Static 00051 // Description: Atomically computes var += delta. It is legal for 00052 // delta to be negative. 00053 //////////////////////////////////////////////////////////////////// 00054 INLINE void AtomicAdjustWin32Impl:: 00055 add(TVOLATILE AtomicAdjustWin32Impl::Integer &var, AtomicAdjustWin32Impl::Integer delta) { 00056 assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0); 00057 #ifdef _WIN64 00058 InterlockedAdd64(&var, delta); 00059 #else 00060 AtomicAdjustWin32Impl::Integer orig_value = var; 00061 while (compare_and_exchange(var, orig_value, orig_value + delta) != orig_value) { 00062 orig_value = var; 00063 } 00064 #endif // _WIN64 00065 } 00066 00067 //////////////////////////////////////////////////////////////////// 00068 // Function: AtomicAdjustWin32Impl::set 00069 // Access: Public, Static 00070 // Description: Atomically changes the indicated variable and 00071 // returns the original value. 00072 //////////////////////////////////////////////////////////////////// 00073 INLINE AtomicAdjustWin32Impl::Integer AtomicAdjustWin32Impl:: 00074 set(TVOLATILE AtomicAdjustWin32Impl::Integer &var, 00075 AtomicAdjustWin32Impl::Integer new_value) { 00076 assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0); 00077 #ifdef _WIN64 00078 return InterlockedExchange64(&var, new_value); 00079 #else 00080 return InterlockedExchange(&var, new_value); 00081 #endif // _WIN64 00082 } 00083 00084 //////////////////////////////////////////////////////////////////// 00085 // Function: AtomicAdjustWin32Impl::get 00086 // Access: Public, Static 00087 // Description: Atomically retrieves the snapshot value of the 00088 // indicated variable. This is the only guaranteed safe 00089 // way to retrieve the value that other threads might be 00090 // asynchronously setting, incrementing, or decrementing 00091 // (via other AtomicAjust methods). 00092 //////////////////////////////////////////////////////////////////// 00093 INLINE AtomicAdjustWin32Impl::Integer AtomicAdjustWin32Impl:: 00094 get(const TVOLATILE AtomicAdjustWin32Impl::Integer &var) { 00095 // On Intel platforms, word-aligned loads are atomic (if performed 00096 // in a single instruction). We can't guarantee the compiler will 00097 // generate a single instruction to load this value, but it 00098 // certainly won't happen if its address isn't word-aligned, so make 00099 // sure that's the case. 00100 assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0); 00101 return var; 00102 } 00103 00104 //////////////////////////////////////////////////////////////////// 00105 // Function: AtomicAdjustWin32Impl::set_ptr 00106 // Access: Public, Static 00107 // Description: Atomically changes the indicated variable and 00108 // returns the original value. 00109 //////////////////////////////////////////////////////////////////// 00110 INLINE AtomicAdjustWin32Impl::Pointer AtomicAdjustWin32Impl:: 00111 set_ptr(TVOLATILE AtomicAdjustWin32Impl::Pointer &var, 00112 AtomicAdjustWin32Impl::Pointer new_value) { 00113 assert((((size_t)&var) & (sizeof(Pointer) - 1)) == 0); 00114 return InterlockedExchangePointer(&var, new_value); 00115 } 00116 00117 //////////////////////////////////////////////////////////////////// 00118 // Function: AtomicAdjustWin32Impl::get_ptr 00119 // Access: Public, Static 00120 // Description: Atomically retrieves the snapshot value of the 00121 // indicated variable. This is the only guaranteed safe 00122 // way to retrieve the value that other threads might be 00123 // asynchronously setting, incrementing, or decrementing 00124 // (via other AtomicAjust methods). 00125 //////////////////////////////////////////////////////////////////// 00126 INLINE AtomicAdjustWin32Impl::Pointer AtomicAdjustWin32Impl:: 00127 get_ptr(const TVOLATILE AtomicAdjustWin32Impl::Pointer &var) { 00128 // As in get(), make sure the address is word-aligned. 00129 assert((((size_t)&var) & (sizeof(Pointer) - 1)) == 0); 00130 return var; 00131 } 00132 00133 //////////////////////////////////////////////////////////////////// 00134 // Function: AtomicAdjustWin32Impl::compare_and_exchange 00135 // Access: Public, Static 00136 // Description: Atomic compare and exchange. 00137 // 00138 // If mem is equal to old_value, store new_value in mem. 00139 // In either case, return the original value of mem. 00140 // The caller can test for success by comparing 00141 // return_value == old_value. 00142 // 00143 // The atomic function expressed in pseudo-code: 00144 // 00145 // orig_value = mem; 00146 // if (mem == old_value) { 00147 // mem = new_value; 00148 // } 00149 // return orig_value; 00150 // 00151 //////////////////////////////////////////////////////////////////// 00152 INLINE AtomicAdjustWin32Impl::Integer AtomicAdjustWin32Impl:: 00153 compare_and_exchange(TVOLATILE AtomicAdjustWin32Impl::Integer &mem, 00154 AtomicAdjustWin32Impl::Integer old_value, 00155 AtomicAdjustWin32Impl::Integer new_value) { 00156 assert((((size_t)&mem) & (sizeof(Integer) - 1)) == 0); 00157 // Note that the AtomicAdjust parameter order is different from 00158 // Windows convention! 00159 #ifdef _WIN64 00160 return InterlockedCompareExchange64((TVOLATILE LONGLONG *)&mem, new_value, old_value); 00161 #else 00162 return InterlockedCompareExchange((TVOLATILE LONG *)&mem, new_value, old_value); 00163 #endif // _WIN64 00164 } 00165 00166 //////////////////////////////////////////////////////////////////// 00167 // Function: AtomicAdjustWin32Impl::compare_and_exchange_ptr 00168 // Access: Public, Static 00169 // Description: Atomic compare and exchange. 00170 // 00171 // As above, but works on pointers instead of integers. 00172 //////////////////////////////////////////////////////////////////// 00173 INLINE AtomicAdjustWin32Impl::Pointer AtomicAdjustWin32Impl:: 00174 compare_and_exchange_ptr(TVOLATILE AtomicAdjustWin32Impl::Pointer &mem, 00175 AtomicAdjustWin32Impl::Pointer old_value, 00176 AtomicAdjustWin32Impl::Pointer new_value) { 00177 assert((((size_t)&mem) & (sizeof(Pointer) - 1)) == 0); 00178 // Note that the AtomicAdjust parameter order is different from 00179 // Windows convention! 00180 return InterlockedCompareExchangePointer(&mem, new_value, old_value); 00181 }