Browse Source

attempt to robustify

David Rose 18 years ago
parent
commit
3010785e58
2 changed files with 63 additions and 4 deletions
  1. 54 1
      dtool/src/dtoolbase/deletedChain.T
  2. 9 3
      dtool/src/dtoolbase/deletedChain.h

+ 54 - 1
dtool/src/dtoolbase/deletedChain.T

@@ -169,6 +169,32 @@ deallocate(Type *ptr, TypeHandle type_handle) {
 #endif  // DELETED_CHAIN_USE_ATOMIC_EXCHANGE
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DeletedChain::validate
+//       Access: Public
+//  Description: Returns true if the pointer is valid, false if it has
+//               been deleted or if it was never a valid pointer.
+//
+//               This is only meaningful in debug mode, where
+//               USE_DELETEDCHAINFLAG is defined.  If not, this
+//               trivially returns true.
+////////////////////////////////////////////////////////////////////
+template<class Type>
+INLINE bool DeletedChain<Type>::
+validate(const Type *ptr) {
+  TAU_PROFILE("bool DeletedChain<Type>::validate(Type *)", " ", TAU_USER);
+  if (ptr == (Type *)NULL) {
+    return false;
+  }
+
+#ifdef USE_DELETEDCHAINFLAG
+  TVOLATILE const ObjectNode *obj = type_to_node((Type *)ptr);
+  return AtomicAdjust::get(obj->_flag) == DCF_alive;
+#else
+  return true;
+#endif  // NDEBUG
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DeletedChain::node_to_type
 //       Access: Private, Static
@@ -213,7 +239,34 @@ template<class Type>
 INLINE void DeletedChain<Type>::
 init_lock() {
   if (_lock == (MutexImpl *)NULL) {
-    _lock = new MutexImpl;
+    do_init_lock();
+  }
+}
+#endif  // DELETED_CHAIN_USE_ATOMIC_EXCHANGE
+
+#ifndef DELETED_CHAIN_USE_ATOMIC_EXCHANGE
+////////////////////////////////////////////////////////////////////
+//     Function: DeletedChain::do_init_lock
+//       Access: Private
+//  Description: Allocates the lock pointer if necessary.  Makes some
+//               pains to protect itself from race conditions.
+////////////////////////////////////////////////////////////////////
+template<class Type>
+void DeletedChain<Type>::
+do_init_lock() {
+  MutexImpl *lock = new MutexImpl;
+
+  // Even though DELETED_CHAIN_USE_ATOMIC_EXCHANGE is not true, we
+  // will take advantage of the atomic exchange operation here, at
+  // startup.  We have to rely on something, after all, before we have
+  // created the first mutex.
+  MutexImpl *result;
+  result = (MutexImpl *)AtomicAdjust::compare_and_exchange_ptr((void * TVOLATILE &)_lock, (void *)NULL, (void *)lock);
+  
+  if (result != NULL) {
+    delete lock;
   }
+  
+  assert(_lock != (MutexImpl *)NULL);
 }
 #endif  // DELETED_CHAIN_USE_ATOMIC_EXCHANGE

+ 9 - 3
dtool/src/dtoolbase/deletedChain.h

@@ -39,7 +39,7 @@
 #endif
 
 #ifndef NDEBUG
-// In development mode, we defined USE_DELETEDCHAINFLAG, which
+// In development mode, we define USE_DELETEDCHAINFLAG, which
 // triggers the piggyback of an additional word of data on every
 // allocated block, so we can ensure that an object is not
 // double-deleted and that the deleted chain remains intact.
@@ -85,6 +85,8 @@ public:
   INLINE static Type *allocate(size_t size, TypeHandle type_handle);
   INLINE static void deallocate(Type *ptr, TypeHandle type_handle);
 
+  INLINE static bool validate(const Type *ptr);
+
 private:
   class ObjectNode {
   public:
@@ -117,6 +119,7 @@ private:
   // If we don't have atomic compare-and-exchange, we need to use a
   // Mutex to protect the above linked list.
   static INLINE void init_lock();
+  static void do_init_lock();
   static MutexImpl *_lock;
 #endif
 };
@@ -126,15 +129,18 @@ private:
 // DeletedChain.
 #define ALLOC_DELETED_CHAIN(Type)                            \
   inline void *operator new(size_t size) {                   \
-    return (void *)DeletedChain< Type >::allocate(size, get_type_handle(Type));       \
+    return (void *)DeletedChain< Type >::allocate(size, get_type_handle(Type)); \
   }                                                          \
   inline void *operator new(size_t size, void *ptr) {        \
     return ptr;                                              \
   }                                                          \
   inline void operator delete(void *ptr) {                   \
-    DeletedChain< Type >::deallocate((Type *)ptr, get_type_handle(Type));             \
+    DeletedChain< Type >::deallocate((Type *)ptr, get_type_handle(Type)); \
   }                                                          \
   inline void operator delete(void *, void *) {              \
+  }                                                          \
+  inline static bool validate_ptr(const void *ptr) {         \
+    return DeletedChain< Type >::validate((const Type *)ptr); \
   }
 
 #include "deletedChain.T"