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