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 method casts from a GU_ConstDetailHandle to a GU_DetailHandle. 00153 // Use it carefully. 00154 GU_DetailHandle castAwayConst() const 00155 { return myDetailHandle; } 00156 00157 /// This will acquire a read lock on the GU_Detail. The result is 0 00158 /// if no lock can be acquired, or no underlying detail exists. 00159 /// The returned detail should be passed to unlock(). (Technically, 00160 /// no locking occurs on error, but unlock is a no-op with a 0 gdp) 00161 const GU_Detail *readLock() 00162 { return myDetailHandle.readLock(); } 00163 00164 /// This will unlock one layer of locking. 00165 /// If the passed in gdp is null, no unlocking occurs. 00166 /// Otherwise, the passed in gdp is asserted to match the one 00167 /// which myHandle points to. 00168 void unlock(const GU_Detail *gdp) 00169 { myDetailHandle.unlock(gdp); } 00170 00171 /// Determine if this is a null handle. This means it 00172 /// points to a null handle, or the handle's gdp is null. 00173 bool isNull() const 00174 { return myDetailHandle.isNull(); } 00175 00176 /// Preserve Requests: 00177 /// A preserve request is a request that people create a new 00178 /// GU_DetailHandle rather than editting the current one. It 00179 /// is used by SOPs to determine if it is safe to do an in place 00180 /// cook. 00181 void addPreserveRequest() 00182 { myDetailHandle.addPreserveRequest(); } 00183 void removePreserveRequest() 00184 { myDetailHandle.removePreserveRequest(); } 00185 int getPreserveRequest() const 00186 { return myDetailHandle.getPreserveRequest(); } 00187 00188 private: 00189 GU_DetailHandle myDetailHandle; 00190 }; 00191 00192 /// GU_DetalHandleAutoFOOLock is a utility class to allow the easy extraction 00193 /// of const GU_Detail * from GU_DetailHandles. It uses the C++ scoping 00194 /// mechanism to make the locking & unlocking transparent to the caller. 00195 /// One can thus do: 00196 /// GU_DetailHandleAutoFOOLock gdl(sop->getCookedGeo()) 00197 /// const GU_Detail *gdp = gdl.getGdp(); 00198 /// The FOO = Read returns const GU_Details and does a read lock. 00199 /// The FOO = Write returns non-const GU_Details and does a write lock. 00200 /// 00201 class 00202 GU_DetailHandleAutoReadLock 00203 { 00204 public: 00205 GU_DetailHandleAutoReadLock(const GU_ConstDetailHandle &handle) 00206 { 00207 myHandle = handle; 00208 myGdp = myHandle.readLock(); 00209 } 00210 GU_DetailHandleAutoReadLock(const GU_DetailHandle &handle) 00211 { 00212 myHandle = handle; 00213 myGdp = myHandle.readLock(); 00214 } 00215 ~GU_DetailHandleAutoReadLock() 00216 { 00217 myHandle.unlock(myGdp); 00218 } 00219 00220 const GU_Detail *getGdp() const { return myGdp; } 00221 00222 private: 00223 GU_ConstDetailHandle myHandle; 00224 const GU_Detail *myGdp; 00225 }; 00226 00227 class 00228 GU_DetailHandleAutoWriteLock 00229 { 00230 public: 00231 GU_DetailHandleAutoWriteLock(const GU_DetailHandle &handle) 00232 { 00233 myHandle = handle; 00234 myGdp = myHandle.writeLock(); 00235 } 00236 ~GU_DetailHandleAutoWriteLock() 00237 { 00238 myHandle.unlock(myGdp); 00239 } 00240 00241 GU_Detail *getGdp() const { return myGdp; } 00242 00243 private: 00244 GU_DetailHandle myHandle; 00245 GU_Detail *myGdp; 00246 }; 00247 00248 #endif 00249
1.5.9