open_toontown_panda3d/dtool/src/dtoolbase/neverFreeMemory.cxx

91 lines
2.3 KiB
C++

/**
* 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."
*
* @file neverFreeMemory.cxx
* @author drose
* @date 2007-06-14
*/
#include "neverFreeMemory.h"
#include "atomicAdjust.h"
#include "memoryHook.h"
NeverFreeMemory * TVOLATILE NeverFreeMemory::_global_ptr;
// If a page has fewer than this many bytes remaining, never mind about it.
static const size_t min_page_remaining_size = 16;
// We always allocate at least this many bytes at a time.
static const size_t min_page_size = 128 * 1024; // 128K
/**
*
*/
NeverFreeMemory::
NeverFreeMemory() {
_total_alloc = 0;
_total_used = 0;
}
/**
*
*/
void *NeverFreeMemory::
ns_alloc(size_t size) {
_lock.lock();
//NB: we no longer do alignment here. The only class that uses this is
// DeletedBufferChain, and we can do the alignment potentially more
// efficiently there since we don't end up overallocating as much.
_total_used += size;
// Look for a page that has sufficient space remaining.
Pages::iterator pi = _pages.lower_bound(Page(NULL, size));
if (pi != _pages.end()) {
// Here's a page with enough remaining space.
Page page = (*pi);
_pages.erase(pi);
void *result = page.alloc(size);
if (page._remaining >= min_page_remaining_size) {
_pages.insert(page);
}
_lock.unlock();
return result;
}
// We have to allocate a new page. Allocate at least min_page_size bytes,
// and then round that up to the next _page_size bytes.
size_t needed_size = max(size, min_page_size);
needed_size = memory_hook->round_up_to_page_size(needed_size);
void *start = memory_hook->mmap_alloc(needed_size, false);
_total_alloc += needed_size;
Page page(start, needed_size);
void *result = page.alloc(size);
if (page._remaining >= min_page_remaining_size) {
_pages.insert(page);
}
_lock.unlock();
return result;
}
/**
*
*/
void NeverFreeMemory::
make_global_ptr() {
NeverFreeMemory *ptr = new NeverFreeMemory;
void *result = AtomicAdjust::compare_and_exchange_ptr
((void * TVOLATILE &)_global_ptr, (void *)NULL, (void *)ptr);
if (result != NULL) {
// Someone else got there first.
delete ptr;
}
}