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

E47891-01

coherence/lang/ChainedHandleElement.hpp

00001 /*
00002 * ChainedHandleElement.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_CHAINED_HANDLE_ELEMENT_HPP
00017 #define COH_CHAINED_HANDLE_ELEMENT_HPP
00018 
00019 #include "coherence/lang/compatibility.hpp"
00020 
00021 #include <stdlib.h>
00022 
00023 COH_OPEN_NAMESPACE2(coherence,lang)
00024 
00025 /**
00026 * @internal
00027 *
00028 * The base class for TypedHandles, allowing for reference chaining.  Reference
00029 * chaining is not thread-safe and thus may only be used for handles which are
00030 * not shared across threads.
00031 *
00032 * @author mf  2008.10.20
00033 */
00034 class ChainedHandleElement
00035     {
00036     protected:
00037         /**
00038         * Action to take on unlinking
00039         */
00040         typedef enum
00041             {
00042             action_none   = 0, // no action required, chain still exists
00043             action_flip   = 1, // unlink last handle from handle->view chain
00044             action_detach = 2, // unlink final element of chain
00045             action_error  = 3  // corrupted chain, raise error
00046             } Action;
00047 
00048 
00049     // ----- constructors ---------------------------------------------------
00050 
00051     protected:
00052         /**
00053         * Create an independent element.
00054         */
00055         ChainedHandleElement(bool fView)
00056             : m_fView(fView)
00057             {
00058             // new chain
00059             m_prev = m_next = this;
00060             }
00061 
00062         /**
00063         * Create a dependent element, adding it to a chain.
00064         */
00065         ChainedHandleElement(const ChainedHandleElement& that, bool fView)
00066             : m_prev(&that), m_next(that.m_next), m_fView(fView)
00067             {
00068             // add self to chain
00069             m_next->m_prev = m_prev->m_next = this;
00070             }
00071 
00072         /**
00073         * Create an optionally dependent element.
00074         */
00075         ChainedHandleElement(const ChainedHandleElement* that, bool fView)
00076             : m_fView(fView)
00077             {
00078             if (that)
00079                 {
00080                 // add self to chain
00081                 m_prev = that;
00082                 m_next = that->m_next;
00083                 m_next->m_prev = m_prev->m_next = this;
00084                 }
00085             else
00086                 {
00087                 // new chain
00088                 m_prev = m_next = this;
00089                 }
00090             }
00091 
00092         /**
00093         * No destructor, derived class must perform unlink and take resulting
00094         * action.
00095         */
00096         //~ChainedHandleElement()
00097 
00098 
00099     // ----- ChainedHandleElement interface ---------------------------------
00100 
00101     protected:
00102         /**
00103         * Unlink this element from the chain.
00104         *
00105         * @return the action to be taken
00106         */
00107         Action unlink() const
00108             {
00109             Action nAction =
00110                     this == m_prev /* implies && this == m_next */ ? action_detach
00111                     // COH-9499 - removed m_prev and m_next m_fView pre-checks due to
00112                     // compiler issues with GCC 4.1
00113                   : !m_fView && scan()                             ? action_flip
00114                                                                    : action_none;
00115 
00116             // unlink self from chain
00117             m_prev->m_next = m_next;
00118             m_next->m_prev = m_prev;
00119 
00120             // empty chain
00121             m_prev = m_next = this;
00122 
00123             return nAction;
00124             }
00125 
00126         /**
00127         * Link this element to a new chain.
00128         *
00129         * @param that  the element to link to
00130         *
00131         * @return the action to be taken
00132         */
00133         Action link(const ChainedHandleElement& that) const
00134             {
00135             Action nAction =
00136                     this == m_prev /* implies && this == m_next */ ? action_detach
00137                     // COH-9499 - removed m_prev and m_next m_fView pre-checks due to
00138                     // compiler issues with GCC 4.1
00139                   : !m_fView && scan()                             ? action_flip
00140                                                                    : action_none;
00141 
00142             // unlink self from chain
00143             m_prev->m_next = m_next;
00144             m_next->m_prev = m_prev;
00145 
00146             // link self into new chain
00147             m_prev = &that;
00148             m_next = that.m_next;
00149 
00150             m_next->m_prev = that.m_next = this;
00151 
00152             return nAction;
00153             }
00154 
00155         /**
00156         * Scan the chain for additional handles.
00157         *
00158         * The caller must be a handle, and have found views on both sides.
00159         *
00160         * @return true if this is the only handle in the chain
00161         */
00162         bool scan() const
00163             {
00164             // The current element must be a handle, so we can scan the list
00165             // until we encounter a handle; if it is this element then there
00166             // are no other handles present. While this is a potentially
00167             // expensive call it is also rarely occurs on a non-trivial chain.
00168             // Since you cannot assign a Handle from a View this will only
00169             // happen if multiple Views are injected in the middle of a handle
00170             // chain. Overall this minimal rare cost is more than worth it as
00171             // it allows chaining of Handles and Views, which removes the far
00172             // more expensive (potentially atomic) reference count increment
00173             // for the common pattern of passing a Handle to a function which
00174             // takes a View.
00175             ChainedHandleElement const* pElm;
00176             for (pElm = m_prev; pElm->m_fView; pElm = pElm->m_prev);
00177             return pElm == this;
00178             }
00179 
00180 
00181     // ----- blocked methods ------------------------------------------------
00182 
00183     private:
00184         /**
00185         * Blocked dynamic allocation.
00186         */
00187         static void* operator new(size_t cb);
00188 
00189 
00190     // ----- data members ---------------------------------------------------
00191 
00192     protected:
00193         /**
00194         * The previous element in the chain.
00195         */
00196         mutable ChainedHandleElement const* m_prev;
00197 
00198         /**
00199         * The next element in the chain.
00200         */
00201         mutable ChainedHandleElement const* m_next;
00202 
00203         /**
00204         * Flag indicating if the associated handle is a view.
00205         */
00206         bool m_fView;
00207 
00208 
00209     // ----- friends --------------------------------------------------------
00210 
00211     /**
00212     * @internal
00213     */
00214     template<class> friend class TypedHandle;
00215     };
00216 
00217 COH_CLOSE_NAMESPACE2
00218 
00219 #endif // COH_CHAINED_HANDLE_ELEMENT_HPP
Copyright © 2000, 2014, Oracle and/or its affiliates. All rights reserved.