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