coherence/lang/SynchronizedBlock.hpp

00001 /*
00002 * SynchronizedBlock.hpp
00003 *
00004 * Copyright (c) 2000, 2009, 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_BLOCK_HPP
00017 #define COH_SYNCHRONIZED_BLOCK_HPP
00018 
00019 #include "coherence/lang/compatibility.hpp"
00020 
00021 #include "coherence/lang/IllegalStateException.hpp"
00022 #include "coherence/lang/Object.hpp"
00023 
00024 #include <sstream>
00025 
00026 COH_OPEN_NAMESPACE2(coherence,lang)
00027 
00028 
00029 /**
00030 * The SynchronizedBlock class allows for easy creation of synchronized code
00031 * blocks based on an Object's monitor. The SynchronizedBlock object will
00032 * ensure that the monitor is entered and exited as part of starting and
00033 * ending the code block.
00034 *
00035 * Example usage:
00036 *
00037 * // outside of sync block
00038 *     {
00039 *     SynchronizedBlock sync(vObject);
00040 *     // monitor entered
00041 *     // critical section goes here
00042 *     // ...
00043 *     } // monitor exited
00044 * // outside of sync block
00045 *
00046 * A more friendly form is to use the COH_SYNCHRONIZED macro. Example usage:
00047 *
00048 * // outside of sync block
00049 * COH_SYNCHRONIZED(vLock) // monitor entered
00050 *   {
00051 *   // critical section goes here
00052 *   // ...
00053 *   // ...
00054 *   } // monitor exited
00055 * // outside of sync block
00056 *
00057 * @author mf 2007.12.09
00058 */
00059 class COH_EXPORT SynchronizedBlock
00060     {
00061     // ----- constructors ---------------------------------------------------
00062 
00063     public:
00064         /**
00065         * Construct a SynchronizedBlock object.
00066         *
00067         * This will automatically enter the monitor.
00068         */
00069         SynchronizedBlock(Object::View v)
00070             : m_cpObject(get_pointer(v)), m_vObject(v)
00071             {
00072             v->_enterMonitor();
00073             }
00074 
00075         /**
00076         * Construct a SynchronizedBlock object from a raw object pointer.
00077         *
00078         * This will automatically enter the monitor.
00079         *
00080         * The caller must ensure that the referenced Object is kept alive for
00081         * the lifetime of the SynchronizedBlock.  This method is generally
00082         * used for synchronizing on "this", which implicitly ensures the
00083         * lifetime guarantee.
00084         */
00085         SynchronizedBlock(const Object* p)
00086             : m_cpObject(p), m_vObject()
00087             {
00088             if (p == NULL)
00089                 {
00090                 coh_throw_npe(typeid(Object));
00091                 }
00092             p->_enterMonitor();
00093             }
00094 
00095         /**
00096         * Copy constructor for COH_SYNCHRONIZED macro.
00097         */
00098         SynchronizedBlock(const SynchronizedBlock& that)
00099             : m_cpObject(that.m_cpObject), m_vObject(that.m_vObject)
00100             {
00101             that.m_cpObject = NULL;
00102             that.m_vObject  = NULL;
00103             }
00104 
00105         /**
00106         * Destroy a SynchronizedBlock object.
00107         *
00108         * This will automatically exit the monitor.
00109         */
00110         ~SynchronizedBlock()
00111             {
00112             const Object* cp = m_cpObject;
00113             if (NULL != cp)
00114                 {
00115                 m_cpObject = NULL;
00116                 cp->_exitMonitor();
00117                 m_vObject  = NULL;
00118                 }
00119             }
00120 
00121 
00122     // ----- operators ------------------------------------------------------
00123 
00124     public:
00125         /*
00126         * Boolean conversion for use in COH_SYNCHRONIZED macro.
00127         *
00128         * @return false if synchronization is held, true otherwise
00129         */
00130         operator bool() const
00131             {
00132             return m_cpObject == NULL;
00133             }
00134 
00135     private:
00136         /**
00137         * Blocked assignment operator.
00138         */
00139         const SynchronizedBlock& operator=(const SynchronizedBlock&);
00140 
00141         /**
00142         * Blocked dynamic allocation.
00143         */
00144         static void* operator new(size_t);
00145 
00146 
00147     // ----- data members ---------------------------------------------------
00148 
00149     protected:
00150         /**
00151         * Raw pointer to Object used to protect the synchronized block.
00152         */
00153         mutable const Object* m_cpObject;
00154 
00155         /**
00156         * Object used to protect the synchronized block.
00157         */
00158         mutable Object::View m_vObject; // on stack
00159     };
00160 
00161 COH_CLOSE_NAMESPACE2
00162 
00163 
00164 /**
00165 * Macro for making more readable synchronized code blocks See the
00166 * documentation of SynchronizedBlock for a usage example.
00167 *
00168 * @see coherence::lang::SynchronizedBlock
00169 */
00170 #define COH_SYNCHRONIZED(V) \
00171     if (coherence::lang::SynchronizedBlock COH_UNIQUE_IDENTIFIER(_coh_sync_) \
00172         = coherence::lang::SynchronizedBlock(V)) \
00173         { \
00174         COH_THROW(coherence::lang::IllegalStateException::create()); \
00175         } \
00176     else
00177 
00178 #endif // COH_SYNCHRONIZED_BLOCK_HPP
Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.