Oracle Fusion Middleware C++ API Reference for Oracle Coherence
12c (12.1.2)

E26041-01

coherence/native/NativeAtomic64.hpp

00001 /*
00002 * NativeAtomic64.hpp
00003 *
00004 * Copyright (c) 2000, 2013, 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
Copyright © 2000, 2013, Oracle and/or its affiliates. All rights reserved.