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