mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-18 20:53:50 -04:00
attempt to robustify
This commit is contained in:
parent
b39ca2fec5
commit
3010785e58
@ -169,6 +169,32 @@ deallocate(Type *ptr, TypeHandle type_handle) {
|
|||||||
#endif // DELETED_CHAIN_USE_ATOMIC_EXCHANGE
|
#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
|
// Function: DeletedChain::node_to_type
|
||||||
// Access: Private, Static
|
// Access: Private, Static
|
||||||
@ -213,7 +239,34 @@ template<class Type>
|
|||||||
INLINE void DeletedChain<Type>::
|
INLINE void DeletedChain<Type>::
|
||||||
init_lock() {
|
init_lock() {
|
||||||
if (_lock == (MutexImpl *)NULL) {
|
if (_lock == (MutexImpl *)NULL) {
|
||||||
_lock = new MutexImpl;
|
do_init_lock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // DELETED_CHAIN_USE_ATOMIC_EXCHANGE
|
#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
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#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
|
// triggers the piggyback of an additional word of data on every
|
||||||
// allocated block, so we can ensure that an object is not
|
// allocated block, so we can ensure that an object is not
|
||||||
// double-deleted and that the deleted chain remains intact.
|
// 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 Type *allocate(size_t size, TypeHandle type_handle);
|
||||||
INLINE static void deallocate(Type *ptr, TypeHandle type_handle);
|
INLINE static void deallocate(Type *ptr, TypeHandle type_handle);
|
||||||
|
|
||||||
|
INLINE static bool validate(const Type *ptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class ObjectNode {
|
class ObjectNode {
|
||||||
public:
|
public:
|
||||||
@ -117,6 +119,7 @@ private:
|
|||||||
// If we don't have atomic compare-and-exchange, we need to use a
|
// If we don't have atomic compare-and-exchange, we need to use a
|
||||||
// Mutex to protect the above linked list.
|
// Mutex to protect the above linked list.
|
||||||
static INLINE void init_lock();
|
static INLINE void init_lock();
|
||||||
|
static void do_init_lock();
|
||||||
static MutexImpl *_lock;
|
static MutexImpl *_lock;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@ -135,6 +138,9 @@ private:
|
|||||||
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 void operator delete(void *, void *) { \
|
||||||
|
} \
|
||||||
|
inline static bool validate_ptr(const void *ptr) { \
|
||||||
|
return DeletedChain< Type >::validate((const Type *)ptr); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "deletedChain.T"
|
#include "deletedChain.T"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user