open_toontown_panda3d/dtool/src/dtoolbase/deletedBufferChain.cxx

141 lines
4.5 KiB
C++

// Filename: deletedBufferChain.cxx
// Created by: drose (20Jul07)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "deletedBufferChain.h"
////////////////////////////////////////////////////////////////////
// Function: DeletedBufferChain::Constructor
// Access: Protected
// Description: Use the global MemoryHook to get a new
// DeletedBufferChain of the appropriate size.
////////////////////////////////////////////////////////////////////
DeletedBufferChain::
DeletedBufferChain(size_t buffer_size) {
_deleted_chain = NULL;
_buffer_size = buffer_size;
_alloc_size = _buffer_size;
#ifdef USE_DELETEDCHAINFLAG
// In development mode, we also need to reserve space for _flag.
_alloc_size += sizeof(AtomicAdjust::Integer);
#endif // NDEBUG
// We must allocate at least this much space for bookkeeping
// reasons.
_buffer_size = max(_buffer_size, sizeof(ObjectNode));
_alloc_size = max(_alloc_size, sizeof(ObjectNode));
}
////////////////////////////////////////////////////////////////////
// Function: DeletedBufferChain::allocate
// Access: Public
// Description: Allocates the memory for a new buffer of the
// indicated size (which must be no greater than the
// fixed size associated with the DeletedBufferChain).
////////////////////////////////////////////////////////////////////
void *DeletedBufferChain::
allocate(size_t size, TypeHandle type_handle) {
#ifdef USE_DELETED_CHAIN
TAU_PROFILE("void *DeletedBufferChain::allocate(size_t, TypeHandle)", " ", TAU_USER);
assert(size <= _buffer_size);
ObjectNode *obj;
_lock.acquire();
if (_deleted_chain != (ObjectNode *)NULL) {
obj = _deleted_chain;
_deleted_chain = _deleted_chain->_next;
_lock.release();
#ifdef USE_DELETEDCHAINFLAG
assert(obj->_flag == (AtomicAdjust::Integer)DCF_deleted);
obj->_flag = DCF_alive;
#endif // NDEBUG
void *ptr = node_to_buffer(obj);
#ifdef DO_MEMORY_USAGE
// type_handle.dec_memory_usage(TypeHandle::MC_deleted_chain_inactive, _alloc_size);
type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, _alloc_size);
#endif // DO_MEMORY_USAGE
return ptr;
}
_lock.release();
// If we get here, the deleted_chain is empty; we have to allocate a
// new object from the system pool.
obj = (ObjectNode *)NeverFreeMemory::alloc(_alloc_size);
#ifdef USE_DELETEDCHAINFLAG
obj->_flag = DCF_alive;
#endif // USE_DELETEDCHAINFLAG
void *ptr = node_to_buffer(obj);
#ifdef DO_MEMORY_USAGE
type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, _alloc_size);
#endif // DO_MEMORY_USAGE
return ptr;
#else // USE_DELETED_CHAIN
return PANDA_MALLOC_SINGLE(_buffer_size);
#endif // USE_DELETED_CHAIN
}
////////////////////////////////////////////////////////////////////
// Function: DeletedBufferChain::deallocate
// Access: Public
// Description: Frees the memory for a buffer previously allocated
// via allocate().
////////////////////////////////////////////////////////////////////
void DeletedBufferChain::
deallocate(void *ptr, TypeHandle type_handle) {
#ifdef USE_DELETED_CHAIN
TAU_PROFILE("void DeletedBufferChain::deallocate(void *, TypeHandle)", " ", TAU_USER);
assert(ptr != (void *)NULL);
#ifdef DO_MEMORY_USAGE
type_handle.dec_memory_usage(TypeHandle::MC_deleted_chain_active, _alloc_size);
// type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_inactive, _alloc_size);
#endif // DO_MEMORY_USAGE
ObjectNode *obj = buffer_to_node(ptr);
#ifdef USE_DELETEDCHAINFLAG
AtomicAdjust::Integer orig_flag = AtomicAdjust::compare_and_exchange(obj->_flag, DCF_alive, DCF_deleted);
// If this assertion is triggered, you double-deleted an object.
assert(orig_flag != (AtomicAdjust::Integer)DCF_deleted);
// If this assertion is triggered, you tried to delete an object
// that was never allocated, or you have heap corruption.
assert(orig_flag == (AtomicAdjust::Integer)DCF_alive);
#endif // NDEBUG
_lock.acquire();
obj->_next = _deleted_chain;
_deleted_chain = obj;
_lock.release();
#else // USE_DELETED_CHAIN
PANDA_FREE_SINGLE(ptr);
#endif // USE_DELETED_CHAIN
}