mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
fix memory leak
This commit is contained in:
parent
5abe3a9e1c
commit
36dfcf2437
@ -17,16 +17,11 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Type>
|
||||
TVOLATILE TYPENAME DeletedChain<Type>::ObjectNode * TVOLATILE DeletedChain<Type>::_deleted_chain;
|
||||
|
||||
#ifndef DELETED_CHAIN_USE_ATOMIC_EXCHANGE
|
||||
template<class Type>
|
||||
MutexImpl *DeletedChain<Type>::_lock;
|
||||
#endif
|
||||
DeletedChain<Type> StaticDeletedChain<Type>::_chain;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DeletedChain::allocate
|
||||
// Access: Public, Static
|
||||
// Access: Public
|
||||
// Description: Allocates the memory for a new object of Type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Type>
|
||||
@ -232,7 +227,7 @@ type_to_node(Type *ptr) {
|
||||
#ifndef DELETED_CHAIN_USE_ATOMIC_EXCHANGE
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DeletedChain::init_lock
|
||||
// Access: Private, Static
|
||||
// Access: Private
|
||||
// Description: Ensures the lock pointer has been allocated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Type>
|
||||
@ -247,7 +242,7 @@ init_lock() {
|
||||
#ifndef DELETED_CHAIN_USE_ATOMIC_EXCHANGE
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DeletedChain::do_init_lock
|
||||
// Access: Private, Static
|
||||
// Access: Private
|
||||
// Description: Allocates the lock pointer if necessary. Takes some
|
||||
// pains to protect itself from race conditions.
|
||||
//
|
||||
@ -275,3 +270,41 @@ do_init_lock(MutexImpl *&lock) {
|
||||
assert(lock != (MutexImpl *)NULL);
|
||||
}
|
||||
#endif // DELETED_CHAIN_USE_ATOMIC_EXCHANGE
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StaticDeletedChain::allocate
|
||||
// Access: Public, Static
|
||||
// Description: Allocates the memory for a new object of Type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Type>
|
||||
INLINE Type *StaticDeletedChain<Type>::
|
||||
allocate(size_t size, TypeHandle type_handle) {
|
||||
return _chain.allocate(size, type_handle);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StaticDeletedChain::deallocate
|
||||
// Access: Public
|
||||
// Description: Frees the memory for an object of Type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Type>
|
||||
INLINE void StaticDeletedChain<Type>::
|
||||
deallocate(Type *ptr, TypeHandle type_handle) {
|
||||
_chain.deallocate(ptr, type_handle);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StaticDeletedChain::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 StaticDeletedChain<Type>::
|
||||
validate(const Type *ptr) {
|
||||
return _chain.validate(ptr);
|
||||
}
|
||||
|
@ -82,10 +82,10 @@ enum DeletedChainFlag {
|
||||
template<class Type>
|
||||
class DeletedChain {
|
||||
public:
|
||||
INLINE static Type *allocate(size_t size, TypeHandle type_handle);
|
||||
INLINE static void deallocate(Type *ptr, TypeHandle type_handle);
|
||||
INLINE Type *allocate(size_t size, TypeHandle type_handle);
|
||||
INLINE void deallocate(Type *ptr, TypeHandle type_handle);
|
||||
|
||||
INLINE static bool validate(const Type *ptr);
|
||||
INLINE bool validate(const Type *ptr);
|
||||
|
||||
private:
|
||||
class ObjectNode {
|
||||
@ -105,44 +105,92 @@ private:
|
||||
TVOLATILE ObjectNode * TVOLATILE _next;
|
||||
};
|
||||
|
||||
INLINE static Type *node_to_type(TVOLATILE ObjectNode *node);
|
||||
INLINE static ObjectNode *type_to_node(Type *ptr);
|
||||
static INLINE Type *node_to_type(TVOLATILE ObjectNode *node);
|
||||
static INLINE ObjectNode *type_to_node(Type *ptr);
|
||||
|
||||
// Ideally, the compiler and linker will unify all references to
|
||||
// this static pointer for a given type, as per the C++ spec.
|
||||
// However, if the compiler fails to do this (*cough* Microsoft), it
|
||||
// won't be a big deal; it just means there will be multiple
|
||||
// unrelated chains of deleted objects for a particular type.
|
||||
static TVOLATILE ObjectNode * TVOLATILE _deleted_chain;
|
||||
TVOLATILE ObjectNode * TVOLATILE _deleted_chain;
|
||||
|
||||
#ifndef DELETED_CHAIN_USE_ATOMIC_EXCHANGE
|
||||
// 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(MutexImpl *&lock);
|
||||
static MutexImpl *_lock;
|
||||
INLINE void init_lock();
|
||||
void do_init_lock(MutexImpl *&lock);
|
||||
MutexImpl *_lock;
|
||||
#endif
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : StaticDeletedChain
|
||||
// Description : This template class is used to conveniently
|
||||
// declare a single instance of the DeletedChain
|
||||
// template object, above, for a particular type.
|
||||
//
|
||||
// It relies on the fact that the compiler and linker
|
||||
// should unify all references to this static pointer
|
||||
// for a given type, as per the C++ spec. However, this
|
||||
// sometimes fails; and if the compiler fails to do
|
||||
// this, it mostly won't be a big deal; it just means
|
||||
// there will be multiple unrelated chains of deleted
|
||||
// objects for a particular type. This is only a
|
||||
// problem if the code structure causes objects to be
|
||||
// allocated from one chain and freed to another, which
|
||||
// can lead to leaks.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Type>
|
||||
class StaticDeletedChain {
|
||||
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);
|
||||
|
||||
static DeletedChain<Type> _chain;
|
||||
};
|
||||
|
||||
// Place this macro within a class definition to define appropriate
|
||||
// operator new and delete methods that take advantage of
|
||||
// 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 *)StaticDeletedChain< 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)); \
|
||||
StaticDeletedChain< 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); \
|
||||
return StaticDeletedChain< Type >::validate((const Type *)ptr); \
|
||||
}
|
||||
|
||||
// Use this variant of the above macro in cases in which the compiler
|
||||
// fails to unify the static template pointers properly, to prevent
|
||||
// leaks.
|
||||
#define ALLOC_DELETED_CHAIN_DECL(Type) \
|
||||
inline void *operator new(size_t size) { \
|
||||
return (void *)_deleted_chain.allocate(size, get_type_handle(Type)); \
|
||||
} \
|
||||
inline void *operator new(size_t size, void *ptr) { \
|
||||
return ptr; \
|
||||
} \
|
||||
inline void operator delete(void *ptr) { \
|
||||
_deleted_chain.deallocate((Type *)ptr, get_type_handle(Type)); \
|
||||
} \
|
||||
inline void operator delete(void *, void *) { \
|
||||
} \
|
||||
inline static bool validate_ptr(const void *ptr) { \
|
||||
return _deleted_chain.validate((const Type *)ptr); \
|
||||
} \
|
||||
static DeletedChain< Type > _deleted_chain;
|
||||
|
||||
// When you use ALLOC_DELETED_CHAIN_DECL in a class body, you must
|
||||
// also put this line in the .cxx file defining that class body.
|
||||
#define ALLOC_DELETED_CHAIN_DEF(Type) \
|
||||
DeletedChain< Type > Type::_deleted_chain;
|
||||
|
||||
#include "deletedChain.T"
|
||||
|
||||
#endif
|
||||
|
@ -29,14 +29,14 @@ allocate(TYPENAME pallocator_single<Type>::size_type n, TYPENAME allocator<void>
|
||||
TAU_PROFILE("pallocator_single:allocate()", " ", TAU_USER);
|
||||
// This doesn't support allocating arrays.
|
||||
assert(n == 1);
|
||||
return DeletedChain<Type>::allocate(sizeof(Type), _type_handle);
|
||||
return StaticDeletedChain<Type>::allocate(sizeof(Type), _type_handle);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
INLINE void pallocator_single<Type>::
|
||||
deallocate(TYPENAME pallocator_single<Type>::pointer p, TYPENAME pallocator_single<Type>::size_type) {
|
||||
TAU_PROFILE("pallocator_single:deallocate()", " ", TAU_USER);
|
||||
return DeletedChain<Type>::deallocate(p, _type_handle);
|
||||
StaticDeletedChain<Type>::deallocate(p, _type_handle);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
|
@ -53,6 +53,8 @@ TypeHandle GeomVertexArrayData::_type_handle;
|
||||
TypeHandle GeomVertexArrayData::CData::_type_handle;
|
||||
TypeHandle GeomVertexArrayDataHandle::_type_handle;
|
||||
|
||||
ALLOC_DELETED_CHAIN_DEF(GeomVertexArrayDataHandle);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomVertexArrayData::Default Constructor
|
||||
// Access: Private
|
||||
|
@ -252,7 +252,7 @@ PUBLISHED:
|
||||
INLINE ~GeomVertexArrayDataHandle();
|
||||
|
||||
public:
|
||||
ALLOC_DELETED_CHAIN(GeomVertexArrayDataHandle);
|
||||
ALLOC_DELETED_CHAIN_DECL(GeomVertexArrayDataHandle);
|
||||
|
||||
INLINE Thread *get_current_thread() const;
|
||||
INLINE const GeomVertexArrayData *get_object() const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user