Panda3D

deletedChain.h

00001 // Filename: deletedChain.h
00002 // Created by:  drose (01Apr06)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #ifndef DELETEDCHAIN_H
00016 #define DELETEDCHAIN_H
00017 
00018 #include "dtoolbase.h"
00019 #include "deletedBufferChain.h"
00020 #include <assert.h>
00021 
00022 ////////////////////////////////////////////////////////////////////
00023 //       Class : DeletedChain
00024 // Description : This template class can be used to provide faster
00025 //               allocation/deallocation for many Panda objects.  It
00026 //               works by maintaining a linked list of deleted objects
00027 //               that are all of the same type; when a new object is
00028 //               allocated that matches that type, the same space is
00029 //               just reused.
00030 //
00031 //               This class is actually a layer on top of
00032 //               DeletedBufferChain, which handles the actual
00033 //               allocation.  This class just provides the
00034 //               typecasting.
00035 //
00036 //               Of course, this trick of maintaining the deleted
00037 //               object chain won't work in the presence of
00038 //               polymorphism, where you might have many classes that
00039 //               derive from a base class, and all of them have a
00040 //               different size--unless you instantiate a DeletedChain
00041 //               for *every* kind of derived class.  The
00042 //               ALLOC_DELETED_CHAIN macro, below, is designed to make
00043 //               this easy.
00044 ////////////////////////////////////////////////////////////////////
00045 template<class Type>
00046 class DeletedChain {
00047 public:
00048   INLINE Type *allocate(size_t size, TypeHandle type_handle);
00049   INLINE void deallocate(Type *ptr, TypeHandle type_handle);
00050 
00051   INLINE bool validate(const Type *ptr);
00052 
00053   static INLINE ReferenceCount *make_ref_ptr(void *ptr);
00054   static INLINE ReferenceCount *make_ref_ptr(ReferenceCount *ptr);
00055 
00056 private:
00057   INLINE void init_deleted_chain();
00058 
00059   DeletedBufferChain *_chain;
00060 };
00061 
00062 ////////////////////////////////////////////////////////////////////
00063 //       Class : StaticDeletedChain
00064 // Description : This template class is used to conveniently
00065 //               declare a single instance of the DeletedChain
00066 //               template object, above, for a particular type.
00067 //
00068 //               It relies on the fact that the compiler and linker
00069 //               should unify all references to this static pointer
00070 //               for a given type, as per the C++ spec. However, this
00071 //               sometimes fails; and if the compiler fails to do
00072 //               this, it mostly won't be a big deal; it just means
00073 //               there will be multiple unrelated chains of deleted
00074 //               objects for a particular type.  This is only a
00075 //               problem if the code structure causes objects to be
00076 //               allocated from one chain and freed to another, which
00077 //               can lead to leaks.
00078 ////////////////////////////////////////////////////////////////////
00079 template<class Type>
00080 class StaticDeletedChain {
00081 public:
00082   INLINE static Type *allocate(size_t size, TypeHandle type_handle);
00083   INLINE static void deallocate(Type *ptr, TypeHandle type_handle);
00084 
00085   INLINE static bool validate(const Type *ptr);
00086 
00087   static DeletedChain<Type> _chain;
00088 };
00089 
00090 #ifdef USE_DELETED_CHAIN
00091 // Place this macro within a class definition to define appropriate
00092 // operator new and delete methods that take advantage of
00093 // DeletedChain.
00094 #define ALLOC_DELETED_CHAIN(Type)                            \
00095   inline void *operator new(size_t size) {                   \
00096     return (void *)StaticDeletedChain< Type >::allocate(size, get_type_handle(Type)); \
00097   }                                                          \
00098   inline void *operator new(size_t size, void *ptr) {        \
00099     return ptr;                                              \
00100   }                                                          \
00101   inline void operator delete(void *ptr) {                   \
00102     StaticDeletedChain< Type >::deallocate((Type *)ptr, get_type_handle(Type)); \
00103   }                                                          \
00104   inline void operator delete(void *, void *) {              \
00105   }                                                          \
00106   inline static bool validate_ptr(const void *ptr) {         \
00107     return StaticDeletedChain< Type >::validate((const Type *)ptr); \
00108   }
00109 
00110 // Use this variant of the above macro in cases in which the compiler
00111 // fails to unify the static template pointers properly, to prevent
00112 // leaks.
00113 #define ALLOC_DELETED_CHAIN_DECL(Type)                       \
00114   inline void *operator new(size_t size) {                   \
00115     return (void *)_deleted_chain.allocate(size, get_type_handle(Type)); \
00116   }                                                          \
00117   inline void *operator new(size_t size, void *ptr) {        \
00118     return ptr;                                              \
00119   }                                                          \
00120   inline void operator delete(void *ptr) {                   \
00121     _deleted_chain.deallocate((Type *)ptr, get_type_handle(Type)); \
00122   }                                                          \
00123   inline void operator delete(void *, void *) {              \
00124   }                                                          \
00125   inline static bool validate_ptr(const void *ptr) {         \
00126     return _deleted_chain.validate((const Type *)ptr);       \
00127   }                                                          \
00128   static DeletedChain< Type > _deleted_chain;
00129 
00130 // When you use ALLOC_DELETED_CHAIN_DECL in a class body, you must
00131 // also put this line in the .cxx file defining that class body.
00132 #define ALLOC_DELETED_CHAIN_DEF(Type)                        \
00133   DeletedChain< Type > Type::_deleted_chain;
00134 
00135 #else  // USE_DELETED_CHAIN
00136 
00137 #define ALLOC_DELETED_CHAIN(Type)                            \
00138   inline static bool validate_ptr(const void *ptr) {         \
00139     return (ptr != NULL);                                    \
00140   }
00141 #define ALLOC_DELETED_CHAIN_DECL(Type)                       \
00142   inline static bool validate_ptr(const void *ptr) {         \
00143     return (ptr != NULL);                                    \
00144   }
00145 #define ALLOC_DELETED_CHAIN_DEF(Type)
00146 
00147 #endif  // USE_DELETED_CHAIN
00148 
00149 #include "deletedChain.T"
00150 
00151 #endif
00152 
 All Classes Functions Variables Enumerations