Oracle Coherence for C++ API
Release 3.7.1.0
E22845-01
00001 /* 00002 * FinalizableBlock.hpp 00003 * 00004 * Copyright (c) 2000, 2011, 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_FINALIZABLE_BLOCK_HPP 00017 #define COH_FINALIZABLE_BLOCK_HPP 00018 00019 #include <stddef.h> 00020 00021 #include "coherence/lang/compatibility.hpp" 00022 00023 COH_OPEN_NAMESPACE2(coherence,lang) 00024 00025 00026 /** 00027 * A finalizable block which runs a series of chained Finalizers as part of 00028 * its destruction. 00029 * 00030 * FinalizableBlocks are useful for cases where a series of finalization 00031 * routines need to be run from a nested function calls. For non-nested 00032 * finalization the use of a FinalizableBlock is unnecessary, and a disposable 00033 * or local class should be used. 00034 */ 00035 class COH_EXPORT FinalizableBlock 00036 { 00037 // ----- constructors --------------------------------------------------- 00038 00039 protected: 00040 /** 00041 * Construct a FinalizableBlock object. 00042 * 00043 * @param pDelegate FinalizableBlock to delegate to, or NULL for 00044 * no delegate 00045 */ 00046 FinalizableBlock(FinalizableBlock* pDelegate = NULL) 00047 : m_pDelegate(NULL), m_pFinalizerHead(NULL) 00048 { 00049 initialize(pDelegate); 00050 } 00051 00052 /** 00053 * Copy constructor. 00054 * 00055 * The new block takes over the ownership of the finalization, the 00056 * supplied block is invalidated, and is not longer usable. 00057 * 00058 * @param that the source block 00059 * 00060 * @see COH_FINALIZABLE 00061 */ 00062 FinalizableBlock(const FinalizableBlock& that) 00063 : m_pDelegate(that.m_pDelegate), m_pFinalizerHead(that.m_pFinalizerHead) 00064 { 00065 // take ownership 00066 that.m_pDelegate = const_cast<FinalizableBlock*>(&that); // marker 00067 that.m_pFinalizerHead = NULL; 00068 } 00069 00070 /** 00071 * Destroy a FinalizableBlock object. 00072 * 00073 * In the case of delegating blocks the destructor has no effect, 00074 * otherwise the finalizer stack is popped, until until all finalizers 00075 * have been deleted. 00076 */ 00077 ~FinalizableBlock() 00078 { 00079 if (isTerminal()) 00080 { 00081 // non-delegate lock, perform lock cleanup 00082 for (Finalizer* pFinalizer = m_pFinalizerHead; NULL != pFinalizer; ) 00083 { 00084 Finalizer* pDelete = pFinalizer; 00085 pFinalizer = pFinalizer->m_pNext; 00086 delete pDelete; 00087 } 00088 } 00089 } 00090 00091 00092 // ----- operators ------------------------------------------------------ 00093 00094 public: 00095 /* 00096 * Boolean conversion for use in COH_FINALIZABLE macro. 00097 * 00098 * @return false always 00099 */ 00100 operator bool() const 00101 { 00102 return false; 00103 } 00104 00105 private: 00106 /** 00107 * Blocked assignment operator. 00108 */ 00109 const FinalizableBlock& operator=(const FinalizableBlock&); 00110 00111 /** 00112 * Blocked dynamic allocation. 00113 */ 00114 static void* operator new(size_t); 00115 00116 00117 // -------- nested class: Finalizer ------------------------------------- 00118 00119 public: 00120 /** 00121 * Interface for custom automatic cleanup operations. 00122 */ 00123 class COH_EXPORT Finalizer 00124 { 00125 // ----- constructor/destructor ---------------------------- 00126 00127 public: 00128 /** 00129 * Finalizer constructor. 00130 */ 00131 Finalizer() 00132 : m_pNext(NULL) 00133 { 00134 } 00135 00136 /** 00137 * Finalizer destructor. 00138 */ 00139 virtual ~Finalizer() 00140 { 00141 } 00142 00143 00144 // ----- data members -------------------------------------- 00145 00146 private: 00147 /** 00148 * Pointer to the next Finalizer on the stack. 00149 */ 00150 Finalizer* m_pNext; 00151 00152 00153 // ----- friends ------------------------------------------- 00154 00155 friend class FinalizableBlock; 00156 }; 00157 00158 00159 // ----- FinalizableBlock interface ------------------------------------- 00160 00161 public: 00162 /** 00163 * Push a custom finalizer onto the FinalizableBlock's 00164 * finalization stack. 00165 * 00166 * If the FinalizableBlock was constructed with a delegate, 00167 * then the finalizer is pushed on the delegates finalizer stack. 00168 * 00169 * The finalizer will then be owned by the FinalizableBlock and will 00170 * be automatically deleted with the top-most FinalizableBlock is 00171 * destroyed. 00172 * 00173 * @param pFinalizer finalizer to add to the finalization stack 00174 */ 00175 void pushFinalizer(Finalizer* pFinalizer) 00176 { 00177 if (isTerminal()) 00178 { 00179 if (pFinalizer == NULL) 00180 { 00181 coh_throw_illegal_argument("NULL finalizer"); 00182 } 00183 pFinalizer->m_pNext = m_pFinalizerHead; 00184 m_pFinalizerHead = pFinalizer; 00185 } 00186 else 00187 { 00188 m_pDelegate->pushFinalizer(pFinalizer); 00189 } 00190 } 00191 00192 protected: 00193 /** 00194 * Return true if the FinalizableBlock is not delegating to 00195 * another FinalizableBlock. 00196 * 00197 * @return return true if the FinalizableBlock is not delegating 00198 * to another FinalizableBlock 00199 */ 00200 bool isTerminal() const 00201 { 00202 FinalizableBlock* pDelegate = m_pDelegate; 00203 if (pDelegate == this) 00204 { 00205 coh_throw_illegal_state( 00206 "attempt to use invalidated FinalizableBlock"); 00207 } 00208 return NULL == pDelegate; 00209 } 00210 00211 00212 /** 00213 * Initialize a FinalizableBlock object. 00214 * 00215 * A block may be re-initialized so long as it has not been assigned a 00216 * delegate, and has no finalization stack. 00217 * 00218 * @param pDelegate FinalizableBlock to delegate to, or NULL for 00219 * no delegate 00220 */ 00221 void initialize(FinalizableBlock* pDelegate = NULL) 00222 { 00223 if (m_pDelegate != NULL || m_pFinalizerHead != NULL) 00224 { 00225 coh_throw_illegal_state(""); 00226 } 00227 m_pDelegate = pDelegate; 00228 } 00229 00230 00231 // ----- data members --------------------------------------------------- 00232 00233 private: 00234 /** 00235 * If non-NULL specified a FinalizableBlock to delegate to. 00236 */ 00237 mutable FinalizableBlock* m_pDelegate; 00238 00239 /** 00240 * The head of the finalizer stack. 00241 */ 00242 mutable Finalizer* m_pFinalizerHead; 00243 }; 00244 00245 COH_CLOSE_NAMESPACE2 00246 00247 /** 00248 * Macro for making more readable finalizable code blocks See the 00249 * documentation of FinalizableBlock for a usage example. 00250 * 00251 * The macro will create a well known FinalizableBlock instance referenceable 00252 * as "finally". 00253 * 00254 * @see coherence::lang::FinalizableBlock 00255 */ 00256 #define COH_FINALIZABLE() \ 00257 if (coherence::lang::FinalizableBlock finally \ 00258 = coherence::lang::FinalizableBlock()) \ 00259 { \ 00260 COH_THROW(coherence::lang::IllegalStateException::create()); \ 00261 } \ 00262 else 00263 00264 #endif // COH_FINALIZABLE_BLOCK_HPP