00001 /* 00002 * LifeCycle.hpp 00003 * 00004 * Copyright (c) 2000, 2019, 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_LIFE_CYCLE_HPP 00017 #define COH_LIFE_CYCLE_HPP 00018 00019 #include "coherence/lang/compatibility.hpp" 00020 00021 COH_OPEN_NAMESPACE2(coherence,lang) 00022 00023 00024 /** 00025 * @internal 00026 * 00027 * LifeCycle is a data structure which maintains the reference counts and 00028 * other key pieces of information related to an Object's life. 00029 * 00030 * This class is used as a snapshot of the multiple NativeAtomic32s representing the 00031 * Object's life-cycle. It is therefore safe to perform multiple 00032 * unsynchronized reads/writes against the individual fields. The snapshot 00033 * can then be written back to the Object's NativeAtomic32 state. 00034 * 00035 * The specific layout of the bit-field is non-public and is subject to 00036 * change. 00037 * 00038 * @author mf 2008.01.28 00039 */ 00040 struct LifeCycle 00041 { 00042 // ---- constructors ---------------------------------------------------- 00043 00044 /** 00045 * Construct a LifeCycle object from a raw int32_t, allowing 00046 * initialization from a NativeAtomic32. 00047 * 00048 * @param nState the 32-bit representation of the state portion of LifeCycle 00049 * @param nRefs the 32-bit representation of the refs portion of LifeCycle 00050 */ 00051 LifeCycle(const int32_t nState = 0, const int32_t nRefs = 0) 00052 : state(nState), refs(nRefs) 00053 { 00054 } 00055 00056 // ----- constants ------------------------------------------------------ 00057 00058 /** 00059 * Field identifiers. 00060 */ 00061 typedef enum 00062 { 00063 life_state, // Object life state 00064 escape_state, // Object thread-escape state 00065 monitor_state, // Monitor inflation state 00066 weak_reference_state, // WeakReference inflation state 00067 handle_count, // Handle reference count 00068 view_count, // View reference count 00069 member_lock_state, // read/write lock state 00070 member_lock_reader_count // read/write lock active reader count 00071 } FieldId; 00072 00073 /** 00074 * Monitor/WeakReference state constants. 00075 */ 00076 typedef enum 00077 { 00078 constructing = 0, // pre onInit 00079 initializing = 1, // inside onInit() 00080 initialized = 2, // post onInit() 00081 destructing = 3 // in delete 00082 } LifeStage; 00083 00084 /** 00085 * Monitor/WeakReference state constants. 00086 */ 00087 typedef enum 00088 { 00089 flat = 0, // lazy element does not exist 00090 inflating = 1, // lazy initialization in progress 00091 inflated = 2 // lazy element is usable 00092 } InflationState; 00093 00094 /** 00095 * Member read/write lock state. 00096 */ 00097 typedef enum 00098 { 00099 gate_open = 0, // read locks may be acquired 00100 gate_closing = 1, // no new read locks may be acquired 00101 gate_closed = 2 // no read locks held, no new read locks may be acquired 00102 } MemberLockState; 00103 00104 /** 00105 * The per-attachment count for escaped handles. 00106 */ 00107 enum 00108 { 00109 escaped_increment = 2 00110 }; 00111 00112 /** 00113 * Limits. 00114 */ 00115 enum 00116 { 00117 max_read_locks = 0xFF, // maximum number of reader threads, before blocking 00118 max_handles = 0x7FFF, // maximum number of handles to an Object 00119 max_views = 0x7FFF // maximum number of views to an Object 00120 }; 00121 00122 00123 // ----- data members --------------------------------------------------- 00124 00125 // Note this is broken into two 32 bit atomics rather then one 64 bit 00126 // atomic as performance testing (at least on Solaris x86) has demonstrated 00127 // that a 64 bit CAS in a 32 bit build is significantly slower then a 00128 // 32 bit CAS. As most operations on LifeCycle don't access all parts of 00129 // the LifeCycle object breaking it up into two 32 bit structs provides 00130 // better performance. 00131 00132 union State 00133 { 00134 State(const int32_t n = 0) : raw(n) {} 00135 00136 /** 00137 * Bit-field representation of state. 00138 */ 00139 struct 00140 { 00141 /** 00142 * The stage of life the object is in. 00143 */ 00144 unsigned int nLifeStage : 2; 00145 00146 /** 00147 * The thread-escape state of the object. 00148 */ 00149 unsigned int fEscaped : 1; 00150 00151 /** 00152 * The InflationState of the Object's monitor. 00153 * 00154 * @see InflationState 00155 */ 00156 unsigned int nMonitor : 2; 00157 00158 /** 00159 * The MemberLockState for the Object. 00160 * 00161 * @see MemberLockState 00162 */ 00163 unsigned int nMemberWriteLockState: 2; 00164 00165 /** 00166 * The number of member read locks held. 00167 * 00168 * A value of max_read_locks indicates that there are too many 00169 * readers and a new reader thread must wait even if the lock is 00170 * currently gate_open. 00171 */ 00172 unsigned int cMemberReadLock : 8; // if changed update max_read_locks 00173 } value; 00174 00175 // ----- operators ------------------------------------------------------ 00176 00177 /** 00178 * Compare two LifeCycles for equality. 00179 * 00180 * @param that the LifeCycle to compare against 00181 * 00182 * @return true if the LifeCycles are equal 00183 */ 00184 bool operator==(const LifeCycle::State& that) 00185 { 00186 return raw == that.raw; 00187 } 00188 00189 /** 00190 * Compare two LifeCycles for equality. 00191 * 00192 * @param that the LifeCycle to compare against 00193 * 00194 * @return true if the LifeCycles are not equal 00195 */ 00196 bool operator!=(const LifeCycle::State& that) 00197 { 00198 return raw != that.raw; 00199 } 00200 00201 /** 00202 * Automatic type conversion to int32_t, allowing a LifeCycle::State instance 00203 * to be stored within a NativeAtomic32. 00204 * 00205 * @return the int32_t representation of the LifeCycle::State 00206 */ 00207 operator int32_t() const 00208 { 00209 return raw; 00210 } 00211 00212 /** 00213 * Raw uninterpreted bit field representation of value 00214 */ 00215 int32_t raw; 00216 } state; 00217 00218 union Refs 00219 { 00220 Refs(const int32_t n = 0) : raw(n) {} 00221 00222 /** 00223 * Bit-field representation of reference counts. 00224 */ 00225 struct 00226 { 00227 /** 00228 * The InflationState of the Object's WeakReference. 00229 * 00230 * @see InflationState 00231 */ 00232 unsigned int nWeakReference : 2; 00233 00234 // Note: The maximum ref count limit is fairly low and if this ever becomes an 00235 // issue we can likely allievate it by having an overlflow space in another 00236 // int32_t. When either of these hit their max value we could push a large 00237 // portion of their current value into the overflow space which would then only 00238 // need to be evaluated when these hit escaped_increment at which point we could 00239 // pull a portion of the overflow count back in to the atomic count. That being 00240 // said this doesn't appear to be necessary at this point as the reference chaining 00241 // which doesn't impact these counters should give us quite a bit of headroom. 00242 00243 /** 00244 * The number of Handles to the Object. 00245 * 00246 * A value of max_handles is considered invalid and is used to 00247 * detect roll over. 00248 */ 00249 unsigned int cHandle : 15; // if changed update max_handles 00250 00251 /** 00252 * The number of Views to the Object. 00253 * 00254 * A value of max_views is considered invalid and is used to 00255 * detect roll over. 00256 */ 00257 unsigned int cView : 15; // if changed update max_views 00258 } value; 00259 00260 00261 // ----- operators ------------------------------------------------------ 00262 00263 /** 00264 * Compare two LifeCycles for equality. 00265 * 00266 * @param that the LifeCycle to compare against 00267 * 00268 * @return true if the LifeCycles are equal 00269 */ 00270 bool operator==(const LifeCycle::Refs& that) 00271 { 00272 return raw == that.raw; 00273 } 00274 00275 /** 00276 * Compare two LifeCycles for equality. 00277 * 00278 * @param that the LifeCycle to compare against 00279 * 00280 * @return true if the LifeCycles are not equal 00281 */ 00282 bool operator!=(const LifeCycle::Refs& that) 00283 { 00284 return raw != that.raw; 00285 } 00286 00287 /** 00288 * Automatic type conversion to int32_t, allowing a LifeCycle::Refs instance 00289 * to be stored within a NativeAtomic32. 00290 * 00291 * @return the int32_t representation of the LifeCycle::Refs 00292 */ 00293 operator int32_t() const 00294 { 00295 return raw; 00296 } 00297 00298 /** 00299 * Raw uninterpreted bit field representation of value 00300 */ 00301 int32_t raw; 00302 } refs; 00303 }; 00304 00305 COH_CLOSE_NAMESPACE2 00306 00307 #endif // COH_LIFE_CYCLE_HPP