Panda3D

atomicAdjustWin32Impl.I

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 }
 All Classes Functions Variables Enumerations