open_toontown_panda3d/dtool/src/dtoolbase/deletedChain.h

153 lines
6.4 KiB
C++

// Filename: deletedChain.h
// Created by: drose (01Apr06)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef DELETEDCHAIN_H
#define DELETEDCHAIN_H
#include "dtoolbase.h"
#include "deletedBufferChain.h"
#include <assert.h>
////////////////////////////////////////////////////////////////////
// Class : DeletedChain
// Description : This template class can be used to provide faster
// allocation/deallocation for many Panda objects. It
// works by maintaining a linked list of deleted objects
// that are all of the same type; when a new object is
// allocated that matches that type, the same space is
// just reused.
//
// This class is actually a layer on top of
// DeletedBufferChain, which handles the actual
// allocation. This class just provides the
// typecasting.
//
// Of course, this trick of maintaining the deleted
// object chain won't work in the presence of
// polymorphism, where you might have many classes that
// derive from a base class, and all of them have a
// different size--unless you instantiate a DeletedChain
// for *every* kind of derived class. The
// ALLOC_DELETED_CHAIN macro, below, is designed to make
// this easy.
////////////////////////////////////////////////////////////////////
template<class Type>
class DeletedChain {
public:
INLINE Type *allocate(size_t size, TypeHandle type_handle);
INLINE void deallocate(Type *ptr, TypeHandle type_handle);
INLINE bool validate(const Type *ptr);
static INLINE ReferenceCount *make_ref_ptr(void *ptr);
static INLINE ReferenceCount *make_ref_ptr(ReferenceCount *ptr);
private:
INLINE void init_deleted_chain();
DeletedBufferChain *_chain;
};
////////////////////////////////////////////////////////////////////
// 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;
};
#ifdef USE_DELETED_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 *)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) { \
StaticDeletedChain< Type >::deallocate((Type *)ptr, get_type_handle(Type)); \
} \
inline void operator delete(void *, void *) { \
} \
inline static bool validate_ptr(const void *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;
#else // USE_DELETED_CHAIN
#define ALLOC_DELETED_CHAIN(Type) \
inline static bool validate_ptr(const void *ptr) { \
return (ptr != NULL); \
}
#define ALLOC_DELETED_CHAIN_DECL(Type) \
inline static bool validate_ptr(const void *ptr) { \
return (ptr != NULL); \
}
#define ALLOC_DELETED_CHAIN_DEF(Type)
#endif // USE_DELETED_CHAIN
#include "deletedChain.T"
#endif