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

E80355-01

coherence/native/NativeAtomic32.hpp

00001 /*
00002 * NativeAtomic32.hpp
00003 *
00004 * Copyright (c) 2000, 2017, 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_ATOMIC32_HPP
00017 #define COH_NATIVE_ATOMIC32_HPP
00018 
00019 #include "coherence/lang/compatibility.hpp"
00020 
00021 COH_OPEN_NAMESPACE2(coherence,native)
00022 
00023 
00024 /**
00025 * @internal
00026 *
00027 * 32-bit atomic integer, providing JSR-133 volatile memory semantics.
00028 *
00029 * @author mf 2015.02.11
00030 */
00031 class COH_EXPORT NativeAtomic32
00032     {
00033     // ----- constructors ---------------------------------------------------
00034 
00035     public:
00036         /**
00037         * Create a new Atomic32, as Atomic32 is not an Object
00038         * it is the responsibility of the caller to eventually
00039         * destroy this object.
00040         *
00041         * @param nValue   the initial value
00042         * @param fAtomic  true if the initial assignment needs synchronization
00043         *
00044         * @return a pointer to the new Atomic32
00045         */
00046         NativeAtomic32(int32_t nValue = 0, bool fAtomic = true)
00047             {
00048             if (fAtomic)
00049                 {
00050                 set(nValue);
00051                 }
00052             else
00053                 {
00054                 poke(nValue);
00055                 }
00056             }
00057 
00058 
00059     // ----- Atomic32 interface ---------------------------------------------
00060 
00061     public:
00062         /**
00063         * Return the current value.
00064         *
00065         * @return the current value
00066         */
00067         int32_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         int32_t peek() const
00078             {
00079             return m_nAtomic;
00080             }
00081 
00082         /**
00083         * Unconditionally set the value in a thread-safe manor.
00084         *
00085         * @param  nValue the new value
00086         */
00087         void set(int32_t nValue);
00088 
00089         /**
00090         * Unconditionally (and in a non thread-safe manor) set the value.
00091         *
00092         * @param  nValue the new value
00093         */
00094         void poke(int32_t nValue)
00095             {
00096             m_nAtomic = nValue;
00097             }
00098 
00099         /**
00100         * Set the value so long as the current value matches the expected value.
00101         *
00102         * @param nAssume  the expected current value
00103         * @param nValue   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         int32_t update(int32_t nAssume, int32_t nValue);
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 nAssume  the expected current value
00120         * @param nValue   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         int32_t update(int32_t nAssume, int32_t nValue, bool fAtomic)
00129             {
00130             if (fAtomic)
00131                 {
00132                 return update(nAssume, nValue);
00133                 }
00134 
00135             int32_t nOld = peek();
00136             if (nOld == nAssume)
00137                 {
00138                 poke(nValue);
00139                 }
00140             return nOld;
00141             }
00142 
00143         /**
00144         * Adjust the NativeAtomic32 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         int32_t postAdjust(int32_t c, bool fSafe = true)
00152             {
00153             int32_t cAssume;
00154             int32_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("NativeAtomic32 overflow");
00164                     }
00165                 cActual = update(cAssume, cAssume + c);
00166                 }
00167             while (cAssume != cActual);
00168             return cAssume;
00169             }
00170 
00171         /**
00172         * Adjust the NativeAtomic32 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         int32_t adjust(int32_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 int32_t value.
00190         *
00191         * Note: This is defined in Integer32.hpp, but we can not include
00192         *       Integer32.hpp, so define it here.
00193         */
00194         static const int32_t min_value = 0x80000000U;
00195 
00196         /**
00197         * A constant for the maximum representable int32_t value.
00198         *
00199         * Note: This is defined in Integer32.hpp, but we can not include
00200         *       Integer32.hpp, so define it here.
00201         */
00202         static const int32_t max_value = 0x7FFFFFFFU;
00203 
00204         /**
00205         * The atomically accessed value, in general this should be word aligned.
00206         */
00207         COH_ALIGN(4, int32_t, m_nAtomic);
00208     };
00209 
00210 COH_CLOSE_NAMESPACE2
00211 
00212 #endif // COH_NATIVE_ATOMIC32_HPP
Copyright © 2000, 2017, Oracle and/or its affiliates. All rights reserved.