Oracle Coherence for C++ API
Release 3.7.1.0

E22845-01

coherence/lang/SmartMember.hpp

00001 /*
00002 * SmartMember.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_SMART_MEMBER_HPP
00017 #define COH_SMART_MEMBER_HPP
00018 
00019 #include "coherence/lang/compatibility.hpp"
00020 
00021 #include "coherence/lang/Object.hpp"
00022 
00023 COH_OPEN_NAMESPACE2(coherence,lang)
00024 
00025 
00026 /**
00027 * Base class for smart data-members of managed Objects.
00028 *
00029 * Smart data-members include additional information regarding their
00030 * life-cycle, including a reference to their enclosing Object (guardian). The
00031 * smart member is initialized with a reference to its guardian, and has the
00032 * same life-cycle as the guardian. Creating a SmartMember which is not a
00033 * data-member of the guardian used during initialization will result in
00034 * unsafe/undefined behavior.
00035 *
00036 * @author mf 2008.01.30
00037 */
00038 class COH_EXPORT SmartMember
00039     {
00040     // ----- nested type: Mutability ----------------------------------------
00041 
00042     public:
00043         /**
00044         * The mutability of the SmartMember.
00045         */
00046         typedef enum
00047             {
00048             inherited         = 0, // matches parent
00049             forever_mutable   = 1, // forever mutable
00050             forever_immutable = 2, // no longer mutable; can't go back
00051             safe_immutable    = 3  // not mutable, and reads don't need
00052                                    // synchronization
00053             } Mutability;
00054 
00055 
00056     // ----- constructor ----------------------------------------------------
00057 
00058     public:
00059         /**
00060         * Construct a new SmartMember
00061         *
00062         * @param oGuardian    the data-member's guardian Object.
00063         * @param nMutability  the mutability of the SmartMember
00064         */
00065         SmartMember(const Object& oGuardian, Mutability nMutability = inherited)
00066             : m_nMutability(nMutability)
00067             {
00068             if (oGuardian._isEscaped())
00069                 {
00070                 m_pGuardian = NULL;
00071                 setGuardian(oGuardian);
00072                 }
00073             else
00074                 {
00075                 m_pGuardian                   = &oGuardian;
00076                 m_pNext                       = oGuardian.m_pSmartMemberStack;
00077                 oGuardian.m_pSmartMemberStack = this;
00078                 }
00079             }
00080 
00081 
00082         /**
00083         * Destruct the SmartMember.
00084         */
00085         virtual ~SmartMember()
00086             {
00087             Object const* pGuardian = m_pGuardian;
00088             if (NULL != pGuardian && !pGuardian->_isEscaped() &&
00089                 this == pGuardian->m_pSmartMemberStack)
00090                 {
00091                 // we are at the top of the stack
00092                 pGuardian->m_pSmartMemberStack = m_pNext;
00093                 }
00094             else
00095                 {
00096                 unlinkGuardian();
00097                 }
00098             }
00099 
00100     protected:
00101         /**
00102         * Construct an orphaned SmartMember.
00103         *
00104         * The smart-member will not be usable until a guardian is assigned.
00105         *
00106         * @see #setGuardian()
00107         */
00108         SmartMember();
00109 
00110     private:
00111         /**
00112         * Blocked copy constructor.
00113         */
00114         SmartMember(const SmartMember&);
00115 
00116 
00117     // ----- operators ------------------------------------------------------
00118 
00119     public:
00120         SmartMember& operator=(const SmartMember& that);
00121 
00122 
00123     // ----- SmartMember interface ------------------------------------------
00124 
00125     protected:
00126         /**
00127         * @internal
00128         *
00129         * Return the guardian Object for this data member.
00130         *
00131         * @return the guardian Object for this data member.
00132         */
00133         const Object& getGuardian() const
00134             {
00135             return *m_pGuardian;
00136             }
00137 
00138         /**
00139         * @internal
00140         *
00141         * Set the guardian for this member.
00142         *
00143         * This method is not thread-safe and should not be called on an
00144         * escaped object.
00145         */
00146         void setGuardian(const Object& oGuardian);
00147 
00148         /**
00149         * @internal
00150         *
00151         * Removes this SmartMember from its guardian.
00152         */
00153         void unlinkGuardian();
00154 
00155 
00156     // ----- life cycle events ----------------------------------------------
00157 
00158     protected:
00159         /**
00160         * Event called once the guardian Object has finished being constructed.
00161         * Specifically when the first attachment is made.
00162         *
00163         * As with all event methods any derived implementation should
00164         * include a call to the super class's implementation.
00165         *
00166         * The default implementation calls the onInit() method of each of the
00167         * Object's SmartMembers.
00168         */
00169         virtual void onInit()
00170             {
00171             }
00172 
00173         /**
00174         * Event called when the guardian Object becomes only referenced via
00175         * const pointers (Views). As the SmartMember is a data-member
00176         * of this Object, the data-member infer that only const methods will
00177         * be called from now on.
00178         *
00179         * Derived implementations of this method should include a delegation
00180         * call to their super class onConst() method, after they've done
00181         * their own processing of the event.
00182         *
00183         * Not that this method will only be called by the guardian if the
00184         * SmartMember's mutability state is set to inherited.
00185         */
00186         virtual void onConst()
00187             {
00188             m_nMutability = forever_immutable;
00189             }
00190 
00191         /**
00192         * Event called when the guarding Object's escape state changes.
00193         *
00194         * Derived implementations of this method should include a delegation
00195         * call to their super class onEscape() method, after they've done
00196         * their own processing of the event.
00197         *
00198         * @param fEscaped  true if the object is being escaped, false if the
00199         *                  object is being captured
00200         */
00201         virtual void onEscape(bool /*fEscaped*/) const
00202             {
00203             if (m_nMutability == forever_immutable)
00204                 {
00205                 // forever_immutable cannot go back to mutable, and we are single threaded
00206                 // at this point any associated "const" value can be safely
00207                 // read without the need for synchronization
00208                 m_nMutability = safe_immutable;
00209                 }
00210             }
00211 
00212 
00213     // ----- data members ---------------------------------------------------
00214 
00215     protected:
00216         /**
00217         * The mutability of the SmartMember.
00218         */
00219         mutable Mutability m_nMutability;
00220 
00221     private:
00222         /**
00223         * The Member's guardian.
00224         */
00225         Object const* m_pGuardian;
00226 
00227         /**
00228         * The next SmartMember in the guardian's SmartMember stack.
00229         */
00230         mutable SmartMember* m_pNext;
00231 
00232 
00233     // ----- friends --------------------------------------------------------
00234 
00235     friend class Object;
00236 
00237     friend const Object& get_guardian(const SmartMember& member);
00238     };
00239 
00240 /**
00241 * @internal
00242 *
00243 * Return the guardian Object for the smart member.
00244 *
00245 * @return the guardian Object for the smart member.
00246 */
00247 inline const Object& get_guardian(const SmartMember& member)
00248     {
00249     return member.getGuardian();
00250     }
00251 
00252 COH_CLOSE_NAMESPACE2
00253 
00254 #endif // COH_SMART_MEMBER_HPP
Copyright © 2000, 2011, Oracle and/or its affiliates. All rights reserved.