C++ Client API Reference for Oracle Coherence
14c (14.1.2.0.0)

F79659-03

coherence/lang/FinalizableBlock.hpp

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