00001 /* 00002 * SynchronizedBlock.hpp 00003 * 00004 * Copyright (c) 2000, 2010, 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