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