00001 /* 00002 * PROPRIETARY INFORMATION. This software is proprietary to 00003 * Side Effects Software Inc., and is not to be reproduced, 00004 * transmitted, or disclosed in any way without written permission. 00005 * 00006 * Produced by: 00007 * Jeff Lait 00008 * Side Effects Software Inc 00009 * 477 Richmond Street West 00010 * Toronto, Ontario 00011 * Canada M5V 3E7 00012 * 416-504-9876 00013 * 00014 * NAME: GU_DetailHandle.h ( GU Library, C++) 00015 * 00016 * COMMENTS: A detail handle is used to maintain a reference to a 00017 * GU_Detail. It provides a level of indirection so that 00018 * the underlying GU_Detail may be deleted or changed 00019 * without those interested in the GU_Detail having to tell. 00020 * It also provides write/read lock tests to allow memory 00021 * managers to tell what is safe to be deleted. 00022 */ 00023 00024 #ifndef __GU_DetailHandle__ 00025 #define __GU_DetailHandle__ 00026 00027 #include "GU_API.h" 00028 00029 class GU_Detail; 00030 class GU_DetailHandleRef; 00031 00032 /// A GU_DetailHandle is designed to allow arms length references to 00033 /// GU_Details. The underlying GU_Detail can be deleted or swapped 00034 /// and things which use the GU_DetailHandle will properly be notified. 00035 /// Further, it provides access control to the GU_Detail, ensuring multiple 00036 /// entities do not write to it at once. This is currently used to ensure 00037 /// deletion is not performed on active GU_Details. Eventually it could 00038 /// be used for multi-threaded support. 00039 class GU_API GU_DetailHandle 00040 { 00041 public: 00042 GU_DetailHandle(); 00043 GU_DetailHandle(const GU_DetailHandle &handle); 00044 00045 ~GU_DetailHandle(); 00046 00047 void clear(); 00048 00049 const GU_DetailHandle &operator=(const GU_DetailHandle &handle); 00050 00051 bool operator==(const GU_DetailHandle &handle) const; 00052 bool operator!=(const GU_DetailHandle &handle) const; 00053 00054 /// peekDetail does no locking. Thus, it should be avoided unless 00055 /// the goal is just to test if the GU_Detail is present. This 00056 /// is largely provided for supporting old code in hackish situations. 00057 const GU_Detail *peekDetail() const; 00058 00059 /// This will acquire a read lock on the GU_Detail. The result is 0 00060 /// if no lock can be acquired, or no underlying detail exists. 00061 /// The returned detail should be passed to unlock(). (Technically, 00062 /// no locking occurs on error, but unlock is a no-op with a 0 gdp) 00063 const GU_Detail *readLock(); 00064 00065 /// This will acquire a write lock on the GU_Detail. The result is 0 00066 /// if no lock can be acquired, or no underlying detail is present. 00067 /// The returned detail should be passed to unlock() when finished. 00068 /// There can only be one active write lock at a time. Do not destroy 00069 /// or modify the pointer itself and expect the unlock to update 00070 /// the GU_Detail *. Instead, use one of the delete or change functions. 00071 /// No readlocks or write locks can be active for this to work. 00072 GU_Detail *writeLock(); 00073 00074 /// This will unlock one layer of locking. 00075 /// If the passed in gdp is null, no unlocking occurs. 00076 /// Otherwise, the passed in gdp is asserted to match the one 00077 /// which myHandle points to. 00078 void unlock(const GU_Detail *gdp); 00079 00080 /// This changes the underlying gdp of the handle. The old 00081 /// gdp is returned. It is asserted that no locks are active. 00082 /// If there is an active lock, the passed in gdp is returned. 00083 GU_Detail *setGdp(GU_Detail *gdp); 00084 00085 /// Create a new underlying reference & set it to point to the 00086 /// given gdp. 00087 /// The own flag determines if the GU_Detail will be deleted by 00088 /// the handle system when the underlying reference is deleted. 00089 void allocateAndSet(GU_Detail *gdp, bool own=true); 00090 00091 /// Deletes the underlying gdp and sets the gdp pointer to be null. 00092 /// It returns true if the gdp was successfully deleted, false if not. 00093 /// Failure likely results from a lock being present. 00094 bool deleteGdp(); 00095 00096 /// Determines if anyone has a lock on this handle. 00097 bool hasActiveLock() const; 00098 00099 /// Determine if this is a null handle. This means it 00100 /// points to a null handle, or the handle's gdp is null. 00101 bool isNull() const; 00102 00103 /// Returns the number of references made to the base handle. 00104 int getRefCount() const; 00105 00106 /// Preserve Requests: 00107 /// A preserve request is a request that people create a new 00108 /// GU_DetailHandle rather than editting the current one. It 00109 /// is used by SOPs to determine if it is safe to do an in place 00110 /// cook. 00111 void addPreserveRequest(); 00112 void removePreserveRequest(); 00113 int getPreserveRequest() const; 00114 00115 private: 00116 GU_DetailHandleRef *myHandle; 00117 }; 00118 00119 /// A GU_ConstDetailHandle uses a GU_DetailHandle to provide const-only 00120 /// access to a GU_Detail. It uses a GU_DetailHandle member variable to 00121 /// do all the actual work, and simply hides any functionality that is 00122 /// unsafe or inappropriate for a const GU_Detail. 00123 class GU_API GU_ConstDetailHandle 00124 { 00125 public: 00126 GU_ConstDetailHandle() 00127 { } 00128 GU_ConstDetailHandle(const GU_ConstDetailHandle &handle) 00129 { myDetailHandle = handle.myDetailHandle; } 00130 GU_ConstDetailHandle(const GU_DetailHandle &handle) 00131 { myDetailHandle = handle; } 00132 00133 ~GU_ConstDetailHandle() 00134 { } 00135 00136 const GU_ConstDetailHandle &operator=(const GU_ConstDetailHandle &handle) 00137 { 00138 myDetailHandle = handle.myDetailHandle; 00139 return *this; 00140 } 00141 const GU_ConstDetailHandle &operator=(const GU_DetailHandle &handle) 00142 { 00143 myDetailHandle = handle; 00144 return *this; 00145 } 00146 00147 bool operator==(const GU_ConstDetailHandle &handle) const 00148 { return myDetailHandle == handle.myDetailHandle; } 00149 bool operator!=(const GU_ConstDetailHandle &handle) const 00150 { return myDetailHandle != handle.myDetailHandle; } 00151 00152 /// This will acquire a read lock on the GU_Detail. The result is 0 00153 /// if no lock can be acquired, or no underlying detail exists. 00154 /// The returned detail should be passed to unlock(). (Technically, 00155 /// no locking occurs on error, but unlock is a no-op with a 0 gdp) 00156 const GU_Detail *readLock() 00157 { return myDetailHandle.readLock(); } 00158 00159 /// This will unlock one layer of locking. 00160 /// If the passed in gdp is null, no unlocking occurs. 00161 /// Otherwise, the passed in gdp is asserted to match the one 00162 /// which myHandle points to. 00163 void unlock(const GU_Detail *gdp) 00164 { myDetailHandle.unlock(gdp); } 00165 00166 /// Determine if this is a null handle. This means it 00167 /// points to a null handle, or the handle's gdp is null. 00168 bool isNull() const 00169 { return myDetailHandle.isNull(); } 00170 00171 /// Preserve Requests: 00172 /// A preserve request is a request that people create a new 00173 /// GU_DetailHandle rather than editting the current one. It 00174 /// is used by SOPs to determine if it is safe to do an in place 00175 /// cook. 00176 void addPreserveRequest() 00177 { myDetailHandle.addPreserveRequest(); } 00178 void removePreserveRequest() 00179 { myDetailHandle.removePreserveRequest(); } 00180 int getPreserveRequest() const 00181 { return myDetailHandle.getPreserveRequest(); } 00182 00183 private: 00184 GU_DetailHandle myDetailHandle; 00185 }; 00186 00187 /// GU_DetalHandleAutoFOOLock is a utility class to allow the easy extraction 00188 /// of const GU_Detail * from GU_DetailHandles. It uses the C++ scoping 00189 /// mechanism to make the locking & unlocking transparent to the caller. 00190 /// One can thus do: 00191 /// GU_DetailHandleAutoFOOLock gdl(sop->getCookedGeo()) 00192 /// const GU_Detail *gdp = gdl.getGdp(); 00193 /// The FOO = Read returns const GU_Details and does a read lock. 00194 /// The FOO = Write returns non-const GU_Details and does a write lock. 00195 /// 00196 class 00197 GU_DetailHandleAutoReadLock 00198 { 00199 public: 00200 GU_DetailHandleAutoReadLock(const GU_ConstDetailHandle &handle) 00201 { 00202 myHandle = handle; 00203 myGdp = myHandle.readLock(); 00204 } 00205 GU_DetailHandleAutoReadLock(const GU_DetailHandle &handle) 00206 { 00207 myHandle = handle; 00208 myGdp = myHandle.readLock(); 00209 } 00210 ~GU_DetailHandleAutoReadLock() 00211 { 00212 myHandle.unlock(myGdp); 00213 } 00214 00215 const GU_Detail *getGdp() const { return myGdp; } 00216 00217 private: 00218 GU_ConstDetailHandle myHandle; 00219 const GU_Detail *myGdp; 00220 }; 00221 00222 class 00223 GU_DetailHandleAutoWriteLock 00224 { 00225 public: 00226 GU_DetailHandleAutoWriteLock(const GU_DetailHandle &handle) 00227 { 00228 myHandle = handle; 00229 myGdp = myHandle.writeLock(); 00230 } 00231 ~GU_DetailHandleAutoWriteLock() 00232 { 00233 myHandle.unlock(myGdp); 00234 } 00235 00236 GU_Detail *getGdp() const { return myGdp; } 00237 00238 private: 00239 GU_DetailHandle myHandle; 00240 GU_Detail *myGdp; 00241 }; 00242 00243 #endif 00244
1.5.9