Panda3D

deletedBufferChain.h

00001 // Filename: deletedBufferChain.h
00002 // Created by:  drose (20Jul07)
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 DELETEDBUFFERCHAIN_H
00016 #define DELETEDBUFFERCHAIN_H
00017 
00018 #include "dtoolbase.h"
00019 #include "neverFreeMemory.h"
00020 #include "mutexImpl.h"
00021 #include "atomicAdjust.h"
00022 #include "numeric_types.h"
00023 #include "typeHandle.h"
00024 #include <assert.h>
00025 
00026 // Though it's tempting, it doesn't seem to be possible to implement
00027 // DeletedBufferChain via the atomic exchange operation.
00028 // Specifically, a pointer may be removed from the head of the chain,
00029 // then the same pointer reinserted in the chain, while another thread
00030 // is waiting; and that thread will not detect the change.  So
00031 // instead, we always use a mutex.
00032 
00033 #ifndef NDEBUG
00034 // In development mode, we define USE_DELETEDCHAINFLAG, which
00035 // triggers the piggyback of an additional word of data on every
00036 // allocated block, so we can ensure that an object is not
00037 // double-deleted and that the deleted chain remains intact.
00038 #define USE_DELETEDCHAINFLAG 1
00039 #endif // NDEBUG
00040 
00041 #ifdef USE_DELETEDCHAINFLAG
00042 enum DeletedChainFlag {
00043   DCF_deleted = 0xfeedba0f,
00044   DCF_alive = 0x12487654,
00045 };
00046 #endif
00047 
00048 ////////////////////////////////////////////////////////////////////
00049 //       Class : DeletedBufferChain
00050 // Description : This template class can be used to provide faster
00051 //               allocation/deallocation for many Panda objects.  It
00052 //               works by maintaining a linked list of deleted buffers
00053 //               that are all of the same size; when a new object is
00054 //               allocated that matches that size, the same space is
00055 //               just reused.
00056 //
00057 //               This class manages untyped buffers of a fixed size.
00058 //               It can be used directly; or it also serves as a
00059 //               backbone for DeletedChain, which is a template class
00060 //               that manages object allocations.
00061 //
00062 //               Use MemoryHook to get a new DeletedBufferChain of a
00063 //               particular size.
00064 ////////////////////////////////////////////////////////////////////
00065 class EXPCL_DTOOL DeletedBufferChain {
00066 protected:
00067   DeletedBufferChain(size_t buffer_size);
00068 
00069 public:
00070   void *allocate(size_t size, TypeHandle type_handle);
00071   void deallocate(void *ptr, TypeHandle type_handle);
00072 
00073   INLINE bool validate(void *ptr);
00074   INLINE size_t get_buffer_size() const;
00075 
00076 private:
00077   class ObjectNode {
00078   public:
00079 #ifdef USE_DELETEDCHAINFLAG
00080     // In development mode, we piggyback this extra data.  This is
00081     // maintained out-of-band from the actual pointer returned, so we
00082     // can safely use this flag to indicate the difference between
00083     // allocated and freed pointers.
00084     TVOLATILE AtomicAdjust::Integer _flag;
00085 #endif
00086 
00087     // This pointer sits within the buffer, in the same space
00088     // referenced by the actual pointer returned (unlike _flag,
00089     // above).  It's only used when the buffer is deleted, so there's
00090     // no harm in sharing space with the undeleted buffer.
00091     ObjectNode *_next;
00092   };
00093 
00094   static INLINE void *node_to_buffer(ObjectNode *node);
00095   static INLINE ObjectNode *buffer_to_node(void *buffer);
00096   static INLINE size_t get_flag_reserved_bytes();
00097 
00098   ObjectNode *_deleted_chain;
00099   
00100   MutexImpl _lock;
00101   size_t _buffer_size;
00102   size_t _alloc_size;
00103 
00104   friend class MemoryHook;
00105 };
00106 
00107 #include "deletedBufferChain.I"
00108 
00109 #endif
00110 
 All Classes Functions Variables Enumerations