attempt to robustify

This commit is contained in:
David Rose 2007-04-03 23:20:18 +00:00
parent b39ca2fec5
commit 3010785e58
2 changed files with 63 additions and 4 deletions

View File

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

View File

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