Panda3D

deletedBufferChain.cxx

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 }
 All Classes Functions Variables Enumerations