Panda3D
deletedChain.h
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file deletedChain.h
10  * @author drose
11  * @date 2006-04-01
12  */
13 
14 #ifndef DELETEDCHAIN_H
15 #define DELETEDCHAIN_H
16 
17 #include "dtoolbase.h"
18 #include "deletedBufferChain.h"
19 #include <assert.h>
20 
21 /**
22  * This template class can be used to provide faster allocation/deallocation
23  * for many Panda objects. It works by maintaining a linked list of deleted
24  * objects that are all of the same type; when a new object is allocated that
25  * matches that type, the same space is just reused.
26  *
27  * This class is actually a layer on top of DeletedBufferChain, which handles
28  * the actual allocation. This class just provides the typecasting.
29  *
30  * Of course, this trick of maintaining the deleted object chain won't work in
31  * the presence of polymorphism, where you might have many classes that derive
32  * from a base class, and all of them have a different size--unless you
33  * instantiate a DeletedChain for *every* kind of derived class. The
34  * ALLOC_DELETED_CHAIN macro, below, is designed to make this easy.
35  */
36 template<class Type>
37 class DeletedChain {
38 public:
39  INLINE Type *allocate(size_t size, TypeHandle type_handle);
40  INLINE void deallocate(Type *ptr, TypeHandle type_handle);
41 
42  INLINE bool validate(const Type *ptr);
43 
44  static INLINE ReferenceCount *make_ref_ptr(void *ptr);
45  static INLINE ReferenceCount *make_ref_ptr(ReferenceCount *ptr);
46 
47 private:
48  INLINE void init_deleted_chain();
49 
50  DeletedBufferChain *_chain;
51 };
52 
53 /**
54  * This template class is used to conveniently declare a single instance of
55  * the DeletedChain template object, above, for a particular type.
56  *
57  * It relies on the fact that the compiler and linker should unify all
58  * references to this static pointer for a given type, as per the C++ spec.
59  * However, this sometimes fails; and if the compiler fails to do this, it
60  * mostly won't be a big deal; it just means there will be multiple unrelated
61  * chains of deleted objects for a particular type. This is only a problem if
62  * the code structure causes objects to be allocated from one chain and freed
63  * to another, which can lead to leaks.
64  */
65 template<class Type>
67 public:
68  INLINE static Type *allocate(size_t size, TypeHandle type_handle);
69  INLINE static void deallocate(Type *ptr, TypeHandle type_handle);
70 
71  INLINE static bool validate(const Type *ptr);
72 
73  static DeletedChain<Type> _chain;
74 };
75 
76 #ifdef USE_DELETED_CHAIN
77 // Place this macro within a class definition to define appropriate operator
78 // new and delete methods that take advantage of DeletedChain.
79 #define ALLOC_DELETED_CHAIN(Type) \
80  inline void *operator new(size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT) { \
81  return (void *)StaticDeletedChain< Type >::allocate(size, get_type_handle(Type)); \
82  } \
83  inline void *operator new(size_t size, void *ptr) { \
84  (void) size; \
85  return ptr; \
86  } \
87  inline void operator delete(void *ptr) { \
88  StaticDeletedChain< Type >::deallocate((Type *)ptr, get_type_handle(Type)); \
89  } \
90  inline void operator delete(void *, void *) { \
91  } \
92  inline static bool validate_ptr(const void *ptr) { \
93  return StaticDeletedChain< Type >::validate((const Type *)ptr); \
94  }
95 
96 // Use this variant of the above macro in cases in which the compiler fails to
97 // unify the static template pointers properly, to prevent leaks.
98 #define ALLOC_DELETED_CHAIN_DECL(Type) \
99  inline void *operator new(size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT) { \
100  return (void *)_deleted_chain.allocate(size, get_type_handle(Type)); \
101  } \
102  inline void *operator new(size_t size, void *ptr) { \
103  (void) size; \
104  return ptr; \
105  } \
106  inline void operator delete(void *ptr) { \
107  _deleted_chain.deallocate((Type *)ptr, get_type_handle(Type)); \
108  } \
109  inline void operator delete(void *, void *) { \
110  } \
111  inline static bool validate_ptr(const void *ptr) { \
112  return _deleted_chain.validate((const Type *)ptr); \
113  } \
114  static DeletedChain< Type > _deleted_chain;
115 
116 // When you use ALLOC_DELETED_CHAIN_DECL in a class body, you must also put
117 // this line in the .cxx file defining that class body.
118 #define ALLOC_DELETED_CHAIN_DEF(Type) \
119  DeletedChain< Type > Type::_deleted_chain;
120 
121 #else // USE_DELETED_CHAIN
122 
123 #define ALLOC_DELETED_CHAIN(Type) \
124  inline static bool validate_ptr(const void *ptr) { \
125  return (ptr != nullptr); \
126  }
127 #define ALLOC_DELETED_CHAIN_DECL(Type) \
128  inline static bool validate_ptr(const void *ptr) { \
129  return (ptr != nullptr); \
130  }
131 #define ALLOC_DELETED_CHAIN_DEF(Type)
132 
133 #endif // USE_DELETED_CHAIN
134 
135 #include "deletedChain.T"
136 
137 #endif
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This template class is used to conveniently declare a single instance of the DeletedChain template ob...
Definition: deletedChain.h:66
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A base class for all things that want to be reference-counted.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
This template class can be used to provide faster allocation/deallocation for many Panda objects.
Definition: deletedChain.h:37
This template class can be used to provide faster allocation/deallocation for many Panda objects.