|
|
@@ -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
|