Panda3D
 All Classes Functions Variables Enumerations
threadSafePointerToBase.I
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> &copy) {
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> &copy) {
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 }
 All Classes Functions Variables Enumerations