Panda3D
|
00001 // Filename: threadSafePointerToBase.I 00002 // Created by: drose (28Apr06) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 00016 //////////////////////////////////////////////////////////////////// 00017 // Function: ThreadSafePointerToBase::Constructor 00018 // Access: Protected 00019 // Description: 00020 //////////////////////////////////////////////////////////////////// 00021 template<class T> 00022 INLINE ThreadSafePointerToBase<T>:: 00023 ThreadSafePointerToBase(To *ptr) { 00024 reassign(ptr); 00025 } 00026 00027 //////////////////////////////////////////////////////////////////// 00028 // Function: ThreadSafePointerToBase::Copy Constructor 00029 // Access: Protected 00030 // Description: 00031 //////////////////////////////////////////////////////////////////// 00032 template<class T> 00033 INLINE ThreadSafePointerToBase<T>:: 00034 ThreadSafePointerToBase(const ThreadSafePointerToBase<T> ©) { 00035 reassign(copy); 00036 } 00037 00038 //////////////////////////////////////////////////////////////////// 00039 // Function: ThreadSafePointerToBase::Destructor 00040 // Access: Protected 00041 // Description: 00042 //////////////////////////////////////////////////////////////////// 00043 template<class T> 00044 INLINE ThreadSafePointerToBase<T>:: 00045 ~ThreadSafePointerToBase() { 00046 reassign((To *)NULL); 00047 } 00048 00049 //////////////////////////////////////////////////////////////////// 00050 // Function: ThreadSafePointerToBase::reassign 00051 // Access: Protected 00052 // Description: This is the main work of the ThreadSafePointerTo family. When 00053 // the pointer is reassigned, decrement the old 00054 // reference count and increment the new one. 00055 //////////////////////////////////////////////////////////////////// 00056 template<class T> 00057 INLINE void ThreadSafePointerToBase<T>:: 00058 reassign(To *ptr) { 00059 To *old_ptr = (To *)AtomicAdjust::get_ptr(_void_ptr); 00060 if (ptr == old_ptr) { 00061 return; 00062 } 00063 00064 #ifdef HAVE_THREADS 00065 void *orig_ptr = AtomicAdjust::compare_and_exchange_ptr(_void_ptr, old_ptr, ptr); 00066 while (orig_ptr != old_ptr) { 00067 // Some other thread assigned it first. Try again. 00068 old_ptr = (To *)AtomicAdjust::get_ptr(_void_ptr); 00069 if (ptr == old_ptr) { 00070 return; 00071 } 00072 00073 orig_ptr = AtomicAdjust::compare_and_exchange_ptr(_void_ptr, old_ptr, ptr); 00074 } 00075 #else // HAVE_THREADS 00076 _void_ptr = ptr; 00077 #endif // HAVE_THREADS 00078 00079 if (ptr != (To *)NULL) { 00080 ptr->ref(); 00081 #ifdef DO_MEMORY_USAGE 00082 if (MemoryUsage::get_track_memory_usage()) { 00083 update_type(ptr); 00084 } 00085 #endif 00086 } 00087 00088 // Now delete the old pointer. 00089 if (old_ptr != (To *)NULL) { 00090 unref_delete(old_ptr); 00091 } 00092 } 00093 00094 //////////////////////////////////////////////////////////////////// 00095 // Function: ThreadSafePointerToBase::reassign 00096 // Access: Protected 00097 // Description: 00098 //////////////////////////////////////////////////////////////////// 00099 template<class T> 00100 INLINE void ThreadSafePointerToBase<T>:: 00101 reassign(const ThreadSafePointerToBase<To> ©) { 00102 reassign((To *)copy._void_ptr); 00103 } 00104 00105 #ifdef DO_MEMORY_USAGE 00106 //////////////////////////////////////////////////////////////////// 00107 // Function: ThreadSafePointerToBase::update_type 00108 // Access: Protected 00109 // Description: Ensures that the MemoryUsage record for the pointer 00110 // has the right type of object, if we know the type 00111 // ourselves. 00112 //////////////////////////////////////////////////////////////////// 00113 template<class T> 00114 void ThreadSafePointerToBase<T>:: 00115 update_type(To *ptr) { 00116 TypeHandle type = get_type_handle(To); 00117 if (type == TypeHandle::none()) { 00118 do_init_type(To); 00119 type = get_type_handle(To); 00120 } 00121 if (type != TypeHandle::none()) { 00122 MemoryUsage::update_type(ptr, type); 00123 } 00124 } 00125 #endif // DO_MEMORY_USAGE 00126 00127 00128 //////////////////////////////////////////////////////////////////// 00129 // Function: ThreadSafePointerToBase::clear 00130 // Access: Published 00131 // Description: A convenient way to set the ThreadSafePointerTo object to NULL. 00132 // (Assignment to a NULL pointer also works, of course.) 00133 //////////////////////////////////////////////////////////////////// 00134 template<class T> 00135 INLINE void ThreadSafePointerToBase<T>:: 00136 clear() { 00137 reassign((To *)NULL); 00138 } 00139 00140 //////////////////////////////////////////////////////////////////// 00141 // Function: ThreadSafePointerToBase::output 00142 // Access: Published 00143 // Description: A handy function to output ThreadSafePointerTo's as a hex 00144 // pointer followed by a reference count. 00145 //////////////////////////////////////////////////////////////////// 00146 template<class T> 00147 INLINE void ThreadSafePointerToBase<T>:: 00148 output(ostream &out) const { 00149 out << _void_ptr; 00150 if (_void_ptr != (void *)NULL) { 00151 out << ":" << ((To *)_void_ptr)->get_ref_count(); 00152 } 00153 }