Panda3D
|
00001 // Filename: deletedBufferChain.cxx 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 #include "deletedBufferChain.h" 00016 00017 //////////////////////////////////////////////////////////////////// 00018 // Function: DeletedBufferChain::Constructor 00019 // Access: Protected 00020 // Description: Use the global MemoryHook to get a new 00021 // DeletedBufferChain of the appropriate size. 00022 //////////////////////////////////////////////////////////////////// 00023 DeletedBufferChain:: 00024 DeletedBufferChain(size_t buffer_size) { 00025 _deleted_chain = NULL; 00026 _buffer_size = buffer_size; 00027 _alloc_size = _buffer_size; 00028 00029 #ifdef USE_DELETEDCHAINFLAG 00030 // In development mode, we also need to reserve space for _flag. 00031 _alloc_size += sizeof(AtomicAdjust::Integer); 00032 #endif // NDEBUG 00033 00034 // We must allocate at least this much space for bookkeeping 00035 // reasons. 00036 _buffer_size = max(_buffer_size, sizeof(ObjectNode)); 00037 _alloc_size = max(_alloc_size, sizeof(ObjectNode)); 00038 } 00039 00040 //////////////////////////////////////////////////////////////////// 00041 // Function: DeletedBufferChain::allocate 00042 // Access: Public 00043 // Description: Allocates the memory for a new buffer of the 00044 // indicated size (which must be no greater than the 00045 // fixed size associated with the DeletedBufferChain). 00046 //////////////////////////////////////////////////////////////////// 00047 void *DeletedBufferChain:: 00048 allocate(size_t size, TypeHandle type_handle) { 00049 #ifdef USE_DELETED_CHAIN 00050 TAU_PROFILE("void *DeletedBufferChain::allocate(size_t, TypeHandle)", " ", TAU_USER); 00051 assert(size <= _buffer_size); 00052 00053 ObjectNode *obj; 00054 00055 _lock.acquire(); 00056 if (_deleted_chain != (ObjectNode *)NULL) { 00057 obj = _deleted_chain; 00058 _deleted_chain = _deleted_chain->_next; 00059 _lock.release(); 00060 00061 #ifdef USE_DELETEDCHAINFLAG 00062 assert(obj->_flag == (AtomicAdjust::Integer)DCF_deleted); 00063 obj->_flag = DCF_alive; 00064 #endif // NDEBUG 00065 00066 void *ptr = node_to_buffer(obj); 00067 00068 #ifdef DO_MEMORY_USAGE 00069 // type_handle.dec_memory_usage(TypeHandle::MC_deleted_chain_inactive, _alloc_size); 00070 type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, _alloc_size); 00071 #endif // DO_MEMORY_USAGE 00072 00073 return ptr; 00074 } 00075 _lock.release(); 00076 00077 // If we get here, the deleted_chain is empty; we have to allocate a 00078 // new object from the system pool. 00079 00080 obj = (ObjectNode *)NeverFreeMemory::alloc(_alloc_size); 00081 00082 #ifdef USE_DELETEDCHAINFLAG 00083 obj->_flag = DCF_alive; 00084 #endif // USE_DELETEDCHAINFLAG 00085 00086 void *ptr = node_to_buffer(obj); 00087 00088 #ifdef DO_MEMORY_USAGE 00089 type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, _alloc_size); 00090 #endif // DO_MEMORY_USAGE 00091 00092 return ptr; 00093 00094 #else // USE_DELETED_CHAIN 00095 return PANDA_MALLOC_SINGLE(_buffer_size); 00096 #endif // USE_DELETED_CHAIN 00097 } 00098 00099 //////////////////////////////////////////////////////////////////// 00100 // Function: DeletedBufferChain::deallocate 00101 // Access: Public 00102 // Description: Frees the memory for a buffer previously allocated 00103 // via allocate(). 00104 //////////////////////////////////////////////////////////////////// 00105 void DeletedBufferChain:: 00106 deallocate(void *ptr, TypeHandle type_handle) { 00107 #ifdef USE_DELETED_CHAIN 00108 TAU_PROFILE("void DeletedBufferChain::deallocate(void *, TypeHandle)", " ", TAU_USER); 00109 assert(ptr != (void *)NULL); 00110 00111 #ifdef DO_MEMORY_USAGE 00112 type_handle.dec_memory_usage(TypeHandle::MC_deleted_chain_active, _alloc_size); 00113 // type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_inactive, _alloc_size); 00114 00115 #endif // DO_MEMORY_USAGE 00116 00117 ObjectNode *obj = buffer_to_node(ptr); 00118 00119 #ifdef USE_DELETEDCHAINFLAG 00120 AtomicAdjust::Integer orig_flag = AtomicAdjust::compare_and_exchange(obj->_flag, DCF_alive, DCF_deleted); 00121 00122 // If this assertion is triggered, you double-deleted an object. 00123 assert(orig_flag != (AtomicAdjust::Integer)DCF_deleted); 00124 00125 // If this assertion is triggered, you tried to delete an object 00126 // that was never allocated, or you have heap corruption. 00127 assert(orig_flag == (AtomicAdjust::Integer)DCF_alive); 00128 #endif // NDEBUG 00129 00130 _lock.acquire(); 00131 00132 obj->_next = _deleted_chain; 00133 _deleted_chain = obj; 00134 00135 _lock.release(); 00136 00137 #else // USE_DELETED_CHAIN 00138 PANDA_FREE_SINGLE(ptr); 00139 #endif // USE_DELETED_CHAIN 00140 }