csutil/weakref.h
Go to the documentation of this file.00001 /* 00002 Crystal Space Weak Reference 00003 Copyright (C) 2003 by Jorrit Tyberghein and Matthias Braun 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public 00016 License along with this library; if not, write to the Free 00017 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 */ 00019 00020 #ifndef __CS_WEAKREF_H__ 00021 #define __CS_WEAKREF_H__ 00022 00027 #include "csextern.h" 00028 #include "csutil/ref.h" 00029 #include "csutil/threading/mutex.h" 00030 00031 struct iBase; 00032 00033 /* Define this macro if you want to get a warning when a weak reference is 00034 * used in a way that is unsafe with multiple threads. */ 00035 #ifdef CS_WEAKREF_WARN_MULTITHREADING_UNSAFE 00036 #define CS_WEAKREF_METHOD_UNSAFE \ 00037 CS_DEPRECATED_METHOD_MSG("UNSAFE in multithreading scenarios - use Get<csRef<> >()") 00038 #else 00039 #define CS_WEAKREF_METHOD_UNSAFE 00040 #endif 00041 00068 template <class T> 00069 class csWeakRef 00070 { 00071 private: 00072 union 00073 { 00074 T* obj; 00075 void* obj_void; 00076 }; 00077 #if defined(CS_DEBUG) 00078 void* this_saved; 00079 #endif 00080 mutable CS::Threading::Mutex obj_mutex; 00081 00087 void Unlink () 00088 { 00089 if (obj) obj->RemoveRefOwner (&obj_void); 00090 } 00091 00095 void Link () 00096 { 00097 if (obj) obj->AddRefOwner (&obj_void, &obj_mutex); 00098 } 00099 00100 public: 00104 csWeakRef () : obj (0) 00105 { 00106 #if defined(CS_DEBUG) 00107 this_saved = this; 00108 #endif 00109 } 00110 00114 csWeakRef (T* newobj) 00115 { 00116 #if defined(CS_DEBUG) 00117 this_saved = this; 00118 #endif 00119 obj = newobj; 00120 Link (); 00121 } 00122 00126 csWeakRef (csRef<T> const& newobj) 00127 { 00128 #if defined(CS_DEBUG) 00129 this_saved = this; 00130 #endif 00131 obj = newobj; 00132 Link (); 00133 } 00134 00138 csWeakRef (csWeakRef const& other) 00139 { 00140 #if defined(CS_DEBUG) 00141 this_saved = this; 00142 #endif 00143 // Keep object from 'other' alive until we linked 00144 typename T::WeakReferencedKeepAlive other_obj_ref; 00145 { 00146 CS::Threading::ScopedLock<CS::Threading::Mutex> lock_other_mutex (other.obj_mutex); 00147 obj = other.obj; 00148 other_obj_ref = obj; 00149 (void)other_obj_ref; 00150 } 00151 Link (); 00152 } 00153 00158 csWeakRef (const csPtr<T>& newobj) 00159 { 00160 #if defined(CS_DEBUG) 00161 this_saved = this; 00162 #endif 00163 csRef<T> r = newobj; 00164 obj = r; 00165 Link (); 00166 } 00167 00171 ~csWeakRef () 00172 { 00173 #if defined(CS_DEBUG) 00174 CS_ASSERT_MSG ("A csWeakRef<> was memcpy()ed, which is not allowed", 00175 this_saved == this); 00176 #endif 00177 /* We need to keep the old object alive for unlinking, 00178 * but we can't keep the obj_mutex locked (possible deadlock 00179 * when the object is in DecRef()) */ 00180 typename T::WeakReferencedKeepAlive obj_ref (Get<typename T::WeakReferencedKeepAlive> ()); 00181 (void)obj_ref; 00182 Unlink (); 00183 } 00184 00188 csWeakRef& operator = (T* newobj) 00189 { 00190 CS::Threading::ScopedLock<CS::Threading::Mutex> lock_mutex (obj_mutex); 00191 if (obj != newobj) 00192 { 00193 { 00194 /* We need to keep the old object alive for unlinking, 00195 * but we can't keep the obj_mutex locked (possible deadlock 00196 * when the object is in DecRef()) */ 00197 typename T::WeakReferencedKeepAlive old_obj_ref (obj); 00198 (void)old_obj_ref; 00199 obj_mutex.Unlock(); 00200 Unlink (); 00201 } 00202 obj_mutex.Lock(); 00203 obj = newobj; 00204 Link (); 00205 } 00206 return *this; 00207 } 00208 00212 csWeakRef& operator = (csRef<T> const& newobj) 00213 { 00214 return (*this = (T*)newobj); 00215 } 00216 00221 csWeakRef& operator = (csPtr<T> newobj) 00222 { 00223 csRef<T> r (newobj); 00224 return (*this = r); 00225 } 00226 00230 csWeakRef& operator = (csWeakRef const& other) 00231 { 00232 this->operator=(other.obj); 00233 return *this; 00234 } 00235 00237 inline friend bool operator == (const csWeakRef& r1, const csWeakRef& r2) 00238 { 00239 CS::Threading::ScopedLock<CS::Threading::Mutex> lock_mutex1 (r1.obj_mutex); 00240 CS::Threading::ScopedLock<CS::Threading::Mutex> lock_mutex2 (r2.obj_mutex); 00241 return r1.obj == r2.obj; 00242 } 00244 inline friend bool operator != (const csWeakRef& r1, const csWeakRef& r2) 00245 { 00246 CS::Threading::ScopedLock<CS::Threading::Mutex> lock_mutex1 (r1.obj_mutex); 00247 CS::Threading::ScopedLock<CS::Threading::Mutex> lock_mutex2 (r2.obj_mutex); 00248 return r1.obj != r2.obj; 00249 } 00251 inline friend bool operator == (const csWeakRef& r1, T* obj) 00252 { 00253 CS::Threading::ScopedLock<CS::Threading::Mutex> lock_mutex1 (r1.obj_mutex); 00254 return r1.obj == obj; 00255 } 00257 inline friend bool operator != (const csWeakRef& r1, T* obj) 00258 { 00259 CS::Threading::ScopedLock<CS::Threading::Mutex> lock_mutex1 (r1.obj_mutex); 00260 return r1.obj != obj; 00261 } 00263 inline friend bool operator == (T* obj, const csWeakRef& r1) 00264 { 00265 CS::Threading::ScopedLock<CS::Threading::Mutex> lock_mutex1 (r1.obj_mutex); 00266 return r1.obj == obj; 00267 } 00269 inline friend bool operator != (T* obj, const csWeakRef& r1) 00270 { 00271 CS::Threading::ScopedLock<CS::Threading::Mutex> lock_mutex1 (r1.obj_mutex); 00272 return r1.obj != obj; 00273 } 00274 00275 inline friend bool operator < (const csWeakRef& r1, const csWeakRef& r2) 00276 { 00277 CS::Threading::ScopedLock<CS::Threading::Mutex> lock_mutex1 (r1.obj_mutex); 00278 CS::Threading::ScopedLock<CS::Threading::Mutex> lock_mutex2 (r2.obj_mutex); 00279 return r1.obj < r2.obj; 00280 } 00281 00283 CS_WEAKREF_METHOD_UNSAFE 00284 T* operator -> () const 00285 { return obj; } 00286 00288 CS_WEAKREF_METHOD_UNSAFE 00289 operator T* () const 00290 { return obj; } 00291 00293 CS_WEAKREF_METHOD_UNSAFE 00294 T& operator* () const 00295 { return *obj; } 00296 00298 00304 template<typename U> 00305 U Get() const 00306 { 00307 CS::Threading::ScopedLock<CS::Threading::Mutex> lock_mutex (obj_mutex); 00308 return U (obj); 00309 } 00310 template<typename U> 00311 void Get(U& ref) const 00312 { 00313 CS::Threading::ScopedLock<CS::Threading::Mutex> lock_mutex (obj_mutex); 00314 ref = obj; 00315 } 00317 00318 00323 CS_WEAKREF_METHOD_UNSAFE 00324 bool IsValid () const 00325 { return (obj != 0); } 00326 00328 uint GetHash() const 00329 { 00330 CS::Threading::ScopedLock<CS::Threading::Mutex> lock_mutex (obj_mutex); 00331 return (uintptr_t)obj; 00332 } 00333 }; 00334 00335 #endif // __CS_WEAKREF_H__ 00336
Generated for Crystal Space 2.1 by doxygen 1.6.1
