00001 /* 00002 * NativeAtomic64.hpp 00003 * 00004 * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. 00005 * 00006 * Oracle is a registered trademarks of Oracle Corporation and/or its 00007 * affiliates. 00008 * 00009 * This software is the confidential and proprietary information of Oracle 00010 * Corporation. You shall not disclose such confidential and proprietary 00011 * information and shall use it only in accordance with the terms of the 00012 * license agreement you entered into with Oracle. 00013 * 00014 * This notice may not be removed or altered. 00015 */ 00016 #ifndef COH_NATIVE_ATOMIC_WORD_HPP 00017 #define COH_NATIVE_ATOMIC_WORD_HPP 00018 00019 #include "coherence/lang/compatibility.hpp" 00020 00021 COH_OPEN_NAMESPACE2(coherence,native) 00022 00023 00024 /** 00025 * @internal 00026 * 00027 * 64-bit atomic integer, providing JSR-133 volatile memory semantics. 00028 * 00029 * @author mf 2007.12.01 00030 */ 00031 class COH_EXPORT NativeAtomic64 00032 { 00033 // ----- constructors --------------------------------------------------- 00034 00035 public: 00036 /** 00037 * Create a new Atomic64, as Atomic64 is not an Object 00038 * it is the responsibility of the caller to eventually 00039 * destroy this object. 00040 * 00041 * @param lValue the initial value 00042 * @param fAtomic true if the initial assignment needs synchronization 00043 * 00044 * @return a pointer to the new Atomic64 00045 */ 00046 NativeAtomic64(int64_t lValue = 0, bool fAtomic = true) 00047 { 00048 if (fAtomic) 00049 { 00050 set(lValue); 00051 } 00052 else 00053 { 00054 poke(lValue); 00055 } 00056 } 00057 00058 00059 // ----- Atomic64 interface --------------------------------------------- 00060 00061 public: 00062 /** 00063 * Return the current value. 00064 * 00065 * @return the current value 00066 */ 00067 int64_t get() const; 00068 00069 /** 00070 * Return the assumed value without performing any memory 00071 * synchronization. This value should not be trusted, but is suitable 00072 * as an assumed value to be passed to update, which will validate if 00073 * it is correct before allowing any associated change to occur. 00074 * 00075 * @return the assumed value 00076 */ 00077 int64_t peek() const 00078 { 00079 return m_lAtomic; 00080 } 00081 00082 /** 00083 * Unconditionally set the value in a thread-safe manor. 00084 * 00085 * @param lValue the new value 00086 */ 00087 void set(int64_t lValue); 00088 00089 /** 00090 * Unconditionally (and in a non thread-safe manor) set the value. 00091 * 00092 * @param lValue the new value 00093 */ 00094 void poke(int64_t lValue) 00095 { 00096 m_lAtomic = lValue; 00097 } 00098 00099 /** 00100 * Set the value so long as the current value matches the expected value. 00101 * 00102 * @param lAssume the expected current value 00103 * @param lValue the new value 00104 * 00105 * @return the prior actual value, if the returned value 00106 * does is not equal to the supplied assumed 00107 * value then update did not take place 00108 */ 00109 int64_t update(int64_t lAssume, int64_t lValue); 00110 00111 /** 00112 * Set the value so long as the current value matches the expected value. 00113 * 00114 * This version of the update method supports conditionally performing 00115 * the update in an unsafe manor. The unsafe update is performed 00116 * without any form of synchronization and should only be used when it 00117 * is known that the object is referenced by a single thread. 00118 * 00119 * @param lAssume the expected current value 00120 * @param lValue the new value 00121 * @param fAtomic perform a safe update operation which can be used 00122 * across threads 00123 * 00124 * @return the prior actual value, if the returned value 00125 * does is not equal to the supplied assumed 00126 * value then update did not take place 00127 */ 00128 int64_t update(int64_t lAssume, int64_t lValue, bool fAtomic) 00129 { 00130 if (fAtomic) 00131 { 00132 return update(lAssume, lValue); 00133 } 00134 00135 int64_t lOld = peek(); 00136 if (lOld == lAssume) 00137 { 00138 poke(lValue); 00139 } 00140 return lOld; 00141 } 00142 00143 /** 00144 * Adjust the NativeAtomic64 by the specified value. 00145 * 00146 * @param c the amount to adjust the atomic by 00147 * @param fSafe to provide overflow protection 00148 * 00149 * @return the old value 00150 */ 00151 int64_t postAdjust(int64_t c, bool fSafe = true) 00152 { 00153 int64_t cAssume; 00154 int64_t cActual = peek(); 00155 do 00156 { 00157 cAssume = cActual; 00158 if (fSafe && 00159 ((c > 0 && cAssume > max_value - c) || 00160 (c < 0 && cAssume < min_value - c ))) 00161 { 00162 // would overflow 00163 coh_throw_illegal_argument("NativeAtomic64 overflow"); 00164 } 00165 cActual = update(cAssume, cAssume + c); 00166 } 00167 while (cAssume != cActual); 00168 return cAssume; 00169 } 00170 00171 /** 00172 * Adjust the NativeAtomic64 by the specified value. 00173 * 00174 * @param c the amount to adjust the atomic by 00175 * @param fSafe to provide overflow protection 00176 * 00177 * @return the adjusted value 00178 */ 00179 int64_t adjust(int64_t c, bool fSafe = true) 00180 { 00181 return postAdjust(c, fSafe) + c; 00182 } 00183 00184 00185 // ----- data members --------------------------------------------------- 00186 00187 private: 00188 /** 00189 * A constant for the minimum representable int64_t value. 00190 * 00191 * Note: This is defined in Integer64.hpp, but we can not include 00192 * Integer64.hpp, so define it here. 00193 */ 00194 static const int64_t min_value = COH_INT64(0x80000000U, 0x0); 00195 00196 /** 00197 * A constant for the maximum representable int64_t value. 00198 * 00199 * Note: This is defined in Integer64.hpp, but we can not include 00200 * Integer64.hpp, so define it here. 00201 */ 00202 static const int64_t max_value = COH_INT64(0x7FFFFFFFU, 0xFFFFFFFFU); 00203 00204 /** 00205 * The atomically accessed value. 00206 */ 00207 int64_t m_lAtomic; 00208 }; 00209 00210 COH_CLOSE_NAMESPACE2 00211 00212 #endif // COH_NATIVE_ATOMIC_WORD_HPP