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

E80355-01

coherence/lang/SynchronizedMemberWriteBlock.hpp

00001 /*
00002 * SynchronizedMemberWriteBlock.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_SYNCHRONIZED_MEMBER_WRITE_BLOCK_HPP
00017 #define COH_SYNCHRONIZED_MEMBER_WRITE_BLOCK_HPP
00018 
00019 #include "coherence/lang/compatibility.hpp"
00020 
00021 #include "coherence/lang/SynchronizedMemberReadBlock.hpp"
00022 
00023 #include <iostream>
00024 
00025 COH_OPEN_NAMESPACE2(coherence,lang)
00026 
00027 
00028 /**
00029 * The SynchronizedMemberBlock class allows for easy creation of synchronized
00030 * code blocks based on an Object's member level read/write lock. The
00031 * SynchronizedMemberBlock object will ensure that the locks are acquired and
00032 * released as part of starting and ending the code block.
00033 *
00034 * Member read/write locks are not a general purpose feature, and should not
00035 * be used to protect blocking calls. They are intended to protect reads and
00036 * writes to data member primitives, and other short non-blocking code
00037 * blocks.
00038 *
00039 * Example usage:
00040 * @code
00041 * // outside of sync block
00042 *     {
00043 *     SynchronizedMemberWriteBlock syncWrite(self()); // write lock
00044 *     acquired // critical section goes here
00045 *     // ...
00046 *     } // write lock released
00047 * // outside of sync block
00048 * @endcode
00049 *
00050 * A more friendly form is to use the COH_SYNCHRONIZED_MEMBER_WRITE
00051 * macros. Example usage:
00052 *
00053 * @code
00054 * // outside of sync block
00055 * COH_SYNCHRONIZED_MEMBER_WRITE // write lock acquired
00056 *   {
00057 *   // critical section goes here
00058 *   // ...
00059 *   // ...
00060 *   } // write lock released
00061 * // outside of sync block
00062 * @endcode
00063 *
00064 * The SynchronizedMemberWriteBlock class relies on its creator to ensure that
00065 * the associated Object outlives the scope of the block. The helper macro
00066 * ensures this by only allowing you to create a block for the encompassing
00067 * Object, i.e. "this". If the blocks are manually created then the caller
00068 * must ensure that the associated Object outlives the block.
00069 *
00070 * Note: This class indirectly derives from FinalizableBlock, allowing custom
00071 * finalizers to be registered. The finalizers will execute after the lock has
00072 * been released.
00073 *
00074 * @author mf 2008.01.29
00075 */
00076 class COH_EXPORT SynchronizedMemberWriteBlock
00077         : public SynchronizedMemberReadBlock
00078     {
00079     // ----- constructors ---------------------------------------------------
00080 
00081     public:
00082         /**
00083         * Construct a synchronized SynchronizedMemberWriteBlock, acquiring the
00084         * Object's member write lock.
00085         *
00086         * @param o          the Object to lock
00087         * @param pDelegate  SynchronizedMemberWriteBlock to delegate to, or
00088         *                   NULL for no delegate
00089         *
00090         * @throws IllegalArgumentException if pSyncDelegate is non-NULL and
00091         *         references a different Object.
00092         */
00093         SynchronizedMemberWriteBlock(const Object& o,
00094                 SynchronizedMemberWriteBlock* pDelegate = NULL)
00095             : SynchronizedMemberReadBlock()
00096             {
00097             initialize(o, pDelegate);
00098             if (isTerminal())
00099                 {
00100                 o._acquireMemberWriteLock();
00101                 }
00102             m_cpObject = &o;
00103             }
00104 
00105         /**
00106         * Destroy a SynchronizedMemberWriteBlock.
00107         *
00108         * This is a no-op for a delegating block, otherwise the write lock is
00109         * released.
00110         */
00111         ~SynchronizedMemberWriteBlock()
00112             {
00113             const Object* cpObject = m_cpObject;
00114             if (NULL != cpObject && isTerminal())
00115                 {
00116                 m_cpObject = NULL; // record that the lock has been released
00117                 try
00118                     {
00119                     cpObject->_releaseMemberWriteLock();
00120                     }
00121                 catch (const std::exception& e)
00122                     {
00123                     std::cerr << "Error releasing MemberWriteLock: " <<
00124                         e.what() << std::endl;
00125                     }
00126                 }
00127             }
00128 
00129 
00130     // ----- SynchronizedMemberWriteBlock interface -------------------------
00131 
00132     public:
00133         /**
00134         * Set the specified member to the specified value, without
00135         * obtaining additional synchronization.
00136         *
00137         * This helper function is only supported on "members" which
00138         * supply a custom two-parameter "set" method utilizing the
00139         * SynchronizedMemberWriteBlock facility.
00140         *
00141         * @param member  the member to set
00142         * @param value   the value to set the member to
00143         */
00144         template<class M, class V> void setMember(M& member, V value)
00145             {
00146             member.set(value, this);
00147             }
00148 
00149         /**
00150         * Set the specified member to the specified value so long as
00151         * the current value is equal to the assumed value.
00152         *
00153         * This helper function is only supported on "members" which
00154         * supply a custom parameterized "set" and "get" methods utilizing the
00155         * SynchronizedMemberWriteBlock facility.
00156         *
00157         * @param member        the member to set
00158         * @param valueAssumed  the assumed current value of the member
00159         * @param valueNew      the value to set the member to
00160         *
00161         * @return the actual value prior to the update attempt
00162         */
00163         template<class M, class V> typename M::GetType updateMember(
00164                     M& member, V valueAssumed, V valueNew)
00165             {
00166             V valueActual = member.get(this);
00167             if (valueAssumed == valueActual)
00168                 {
00169                 member.set(valueNew, this);
00170                 }
00171             return valueActual;
00172             }
00173 
00174         /**
00175         * Set the specified member to the specified value and return the
00176         * previous value.
00177         *
00178         * This helper function is only supported on "members" which
00179         * supply a custom parameterized "set" and "get" methods utilizing the
00180         * SynchronizedMemberWriteBlock facility.
00181         *
00182         * @param member        the member to set
00183         * @param valueNew      the value to set the member to
00184         *
00185         * @return the prior value
00186         */
00187         template<class M, class V> typename M::GetType exchangeMember(
00188                     M& member, V valueNew)
00189             {
00190             V valuePre = member.get(this);
00191             member.set(valueNew, this);
00192             return valuePre;
00193             }
00194 
00195 
00196     // ----- nested class: Guard --------------------------------------------
00197 
00198     public:
00199         /**
00200         * Simple write lock structure for use in inlining.
00201         */
00202         class COH_EXPORT Guard
00203             {
00204             public:
00205                 Guard(const Object& o)
00206                     : m_o(o)
00207                     {
00208                     acquireMemberWriteLock(o);
00209                     }
00210 
00211                 ~Guard()
00212                     {
00213                     releaseMemberWriteLock(m_o);
00214                     }
00215 
00216             private:
00217                 const Object& m_o;
00218             };
00219 
00220 
00221     // ----- helper methods -------------------------------------------------
00222 
00223     protected:
00224         /*
00225         * Acquire an Object's write lock
00226         */
00227         static void acquireMemberWriteLock(const Object& o)
00228             {
00229             o._acquireMemberWriteLock();
00230             }
00231 
00232         /*
00233         * Release an Object's write lock
00234         */
00235         static void releaseMemberWriteLock(const Object& o)
00236             {
00237             o._releaseMemberWriteLock();
00238             }
00239     };
00240 
00241 COH_CLOSE_NAMESPACE2
00242 
00243 
00244 /**
00245 * Macro for making more readable synchronized member write code blocks See the
00246 * documentation of SynchronizedMemberWriteBlock for a usage example.
00247 *
00248 * @see coherence::lang::SynchronizedMemberWriteBlock
00249 */
00250 #define COH_SYNCHRONIZED_MEMBER_WRITE \
00251     if (coherence::lang::SynchronizedMemberWriteBlock coh_synchronized_member_write \
00252         = coherence::lang::SynchronizedMemberWriteBlock(Object::self())) \
00253         { \
00254         COH_THROW(coherence::lang::IllegalStateException::create()); \
00255         } \
00256     else
00257 
00258 #endif // COH_SYNCHRONIZED_MEMBER_WRITE_BLOCK_HPP
Copyright © 2000, 2017, Oracle and/or its affiliates. All rights reserved.