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

E47891-01

coherence/lang/FinalizableBlock.hpp

00001 /*
00002 * FinalizableBlock.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_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_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
Copyright © 2000, 2014, Oracle and/or its affiliates. All rights reserved.