Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2010, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00029 /* */ 00030 /**************************************************************************************/ 00031 00032 #ifndef Object_INCLUDE_ONCE 00033 #define Object_INCLUDE_ONCE 00034 00035 #include <vlCore/checks.hpp> 00036 #include <vlCore/IMutex.hpp> 00037 #include <vlCore/TypeInfo.hpp> 00038 #include <string> 00039 00040 #if VL_DEBUG_LIVING_OBJECTS 00041 #include <set> 00042 #endif 00043 00044 namespace vl 00045 { 00046 template<class T> class ref; 00047 00048 //------------------------------------------------------------------------------ 00049 // Object 00050 //------------------------------------------------------------------------------ 00055 class VLCORE_EXPORT Object 00056 { 00057 VL_INSTRUMENT_BASE_CLASS(vl::Object) 00058 00059 public: 00061 Object() 00062 { 00063 VL_DEBUG_SET_OBJECT_NAME() 00064 mRefCountMutex = NULL; 00065 mReferenceCount = 0; 00066 mAutomaticDelete = true; 00067 // user data 00068 #if VL_OBJECT_USER_DATA 00069 mUserData = NULL; 00070 #endif 00071 #if VL_DEBUG_LIVING_OBJECTS 00072 debug_living_objects()->insert(this); 00073 // mDebug_LivingObjects.insert(this); 00074 #endif 00075 } 00076 00078 Object(const Object& other) 00079 { 00080 // copy the name, the ref count mutex and the user data. 00081 mObjectName = other.mObjectName; 00082 mRefCountMutex = other.mRefCountMutex; 00083 #if VL_OBJECT_USER_DATA 00084 mUserData = other.mUserData; 00085 #endif 00086 00087 // mReferenceCount and mAutomaticDelete are not copiable. 00088 mReferenceCount = 0; 00089 mAutomaticDelete = true; 00090 00091 // debug living object 00092 #if VL_DEBUG_LIVING_OBJECTS 00093 debug_living_objects()->insert(this); 00094 #endif 00095 } 00096 00098 Object& operator=(const Object& other) 00099 { 00100 // copy the name, the ref count mutex and the user data. 00101 mObjectName = other.mObjectName; 00102 mRefCountMutex = other.mRefCountMutex; 00103 #if VL_OBJECT_USER_DATA 00104 mUserData = other.mUserData; 00105 #endif 00106 00107 // mReferenceCount and mAutomaticDelete are not copiable. 00108 // ... 00109 00110 return *this; 00111 } 00112 00114 const std::string& objectName() const { return mObjectName; } 00115 00117 void setObjectName(const char* name) { mObjectName = name; } 00118 00120 void setRefCountMutex(IMutex* mutex) { mRefCountMutex = mutex; } 00121 00123 IMutex* refCountMutex() { return mRefCountMutex; } 00124 00126 const IMutex* refCountMutex() const { return mRefCountMutex; } 00127 00129 int referenceCount() const 00130 { 00131 return mReferenceCount; 00132 } 00133 00135 void incReference() const 00136 { 00137 // Lock mutex 00138 if (refCountMutex()) 00139 const_cast<IMutex*>(refCountMutex())->lock(); 00140 00141 ++mReferenceCount; 00142 00143 // Unlock mutex 00144 if(refCountMutex()) 00145 const_cast<IMutex*>(refCountMutex())->unlock(); 00146 } 00147 00149 void decReference() 00150 { 00151 // Save local copy in case of deletion. 00152 IMutex* mutex = mRefCountMutex; 00153 00154 // Lock mutex. 00155 if (mutex) 00156 mutex->lock(); 00157 00158 VL_CHECK(mReferenceCount) 00159 --mReferenceCount; 00160 if (mReferenceCount == 0 && automaticDelete()) 00161 delete this; 00162 00163 // Unlock mutex. 00164 if (mutex) 00165 mutex->unlock(); 00166 } 00167 00169 void setAutomaticDelete(bool autodel_on) { mAutomaticDelete = autodel_on; } 00170 00172 bool automaticDelete() const { return mAutomaticDelete; } 00173 00175 template<class T> 00176 T* as() { return cast<T>(this); } 00177 00179 template<class T> 00180 const T* as() const { return cast<const T>(this); } 00181 00182 #if VL_OBJECT_USER_DATA 00183 public: 00184 void* userData() { return mUserData; } 00185 const void* userData() const { return mUserData; } 00186 void setUserData(void* user_data) { mUserData = user_data; } 00187 00188 private: 00189 void* mUserData; 00190 #endif 00191 00192 protected: 00193 virtual ~Object(); 00194 std::string mObjectName; 00195 00196 IMutex* mRefCountMutex; 00197 mutable int mReferenceCount; 00198 bool mAutomaticDelete; 00199 00200 // debugging facilities 00201 00202 public: 00203 #if VL_DEBUG_LIVING_OBJECTS 00204 static std::set< Object* >* mDebug_LivingObjects; 00205 static std::set< Object* >* debug_living_objects() 00206 { 00207 if (!mDebug_LivingObjects) 00208 mDebug_LivingObjects = new std::set< Object* >; 00209 return mDebug_LivingObjects; 00210 } 00211 #endif 00212 }; 00213 //------------------------------------------------------------------------------ 00214 // ref 00215 //------------------------------------------------------------------------------ 00221 template<class T> 00222 class ref 00223 { 00224 public: 00225 // 'const' is required as the copy constructor must have this signature. 00226 ref(const ref& other) 00227 { 00228 mObject = NULL; 00229 *this = other; 00230 } 00231 00232 ref(const T* object=NULL) 00233 { 00234 mObject = const_cast<T*>(object); 00235 if (mObject) 00236 mObject->incReference(); 00237 } 00238 00239 template<class T2> ref(const ref<T2>& other) 00240 { 00241 mObject = NULL; 00242 *this = other; 00243 } 00244 00245 ~ref() 00246 { 00247 if (mObject) 00248 mObject->decReference(); 00249 mObject = NULL; 00250 } 00251 00252 // 'const' is required because operator= must have this signature. 00253 ref& operator=(const ref& other) 00254 { 00255 if (other) 00256 other->incReference(); 00257 if (mObject) 00258 mObject->decReference(); 00259 mObject = const_cast<T*>(other.get()); 00260 return *this; 00261 } 00262 00263 // 'const' is required because operator= must have this signature. 00264 ref& operator=(const T* other) 00265 { 00266 if (other) 00267 other->incReference(); 00268 if (mObject) 00269 mObject->decReference(); 00270 mObject = const_cast<T*>(other); 00271 return *this; 00272 } 00273 00274 // 'const' is required because operator= must have this signature. 00275 template<class T2> ref& operator=(const ref<T2>& other) 00276 { 00277 if (other) 00278 other->incReference(); 00279 if (mObject) 00280 mObject->decReference(); 00281 mObject = const_cast<T2*>(other.get()); 00282 return *this; 00283 } 00284 00285 void swap(ref& other) 00286 { 00287 T* tmp = other.mObject; 00288 other = mObject; 00289 mObject = tmp; 00290 } 00291 00293 T* get_writable() const { return mObject; } 00294 00295 const T* get() const { return mObject; } 00296 const T* operator->() const { VL_CHECK(mObject); return mObject; } 00297 const T& operator*() const { VL_CHECK(mObject); return *mObject; } 00298 00299 T* get() { return mObject; } 00300 T* operator->() { VL_CHECK(mObject); return mObject; } 00301 T& operator*() { VL_CHECK(mObject); return *mObject; } 00302 00303 bool operator<(const ref& other) const { return mObject < other.mObject; } 00304 00305 operator bool() const { return mObject != NULL; } 00306 00307 protected: 00308 T* mObject; 00309 }; 00310 // interaction with the other types 00311 template<class T1, class T2> inline bool operator==(const ref<T1> & o1, const ref<T2> & o2) { return o1.get() == o2.get(); } 00312 template<class T1, class T2> inline bool operator!=(const ref<T1> & o1, const ref<T2> & o2) { return o1.get() != o2.get(); } 00313 template<class T1, class T2> inline bool operator==(const ref<T1> & o1, T2 * o2) { return o1.get() == o2; } 00314 template<class T1, class T2> inline bool operator!=(const ref<T1> & o1, T2 * o2) { return o1.get() != o2; } 00315 template<class T1, class T2> inline bool operator==(T1 * o1, const ref<T2> & o2) { return o1 == o2.get(); } 00316 template<class T1, class T2> inline bool operator!=(T1 * o1, const ref<T2> & o2) { return o1 != o2.get(); } 00317 } 00318 00319 #endif