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