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

E47891-01

coherence/lang/SynchronizedMemberWriteBlock.hpp

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