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

E90870-01

coherence/lang/SynchronizedMemberReadBlock.hpp

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