mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
gobj: add alignment support and move semantics to SimpleAllocator
This commit is contained in:
parent
68e7f681f4
commit
f2976b03ec
@ -32,9 +32,9 @@ SimpleAllocator(size_t max_size, Mutex &lock) :
|
||||
* pointer.
|
||||
*/
|
||||
SimpleAllocatorBlock *SimpleAllocator::
|
||||
alloc(size_t size) {
|
||||
alloc(size_t size, size_t alignment) {
|
||||
MutexHolder holder(_lock);
|
||||
return do_alloc(size);
|
||||
return do_alloc(size, alignment);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -148,6 +148,24 @@ SimpleAllocatorBlock(SimpleAllocator *alloc,
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers ownership from the given SimpleAllocatorBlock to this one.
|
||||
*/
|
||||
INLINE SimpleAllocatorBlock::
|
||||
SimpleAllocatorBlock(SimpleAllocatorBlock &&from) :
|
||||
_allocator(from._allocator)
|
||||
{
|
||||
if (_allocator == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexHolder holder(_allocator->_lock);
|
||||
_start = from._start;
|
||||
_size = from._size;
|
||||
LinkedListNode::operator = (std::move(from));
|
||||
from._allocator = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* The block automatically frees itself when it destructs.
|
||||
*/
|
||||
@ -156,6 +174,28 @@ INLINE SimpleAllocatorBlock::
|
||||
free();
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees this block and instead takes ownership of the given other block.
|
||||
*/
|
||||
INLINE SimpleAllocatorBlock &SimpleAllocatorBlock::
|
||||
operator = (SimpleAllocatorBlock &&from) {
|
||||
free();
|
||||
|
||||
_allocator = from._allocator;
|
||||
if (_allocator == nullptr) {
|
||||
_start = 0;
|
||||
_size = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MutexHolder holder(_allocator->_lock);
|
||||
_start = from._start;
|
||||
_size = from._size;
|
||||
LinkedListNode::operator = (std::move(from));
|
||||
from._allocator = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the allocated space.
|
||||
*/
|
||||
|
@ -13,6 +13,37 @@
|
||||
|
||||
#include "simpleAllocator.h"
|
||||
|
||||
/**
|
||||
* Move constructor.
|
||||
*/
|
||||
SimpleAllocator::
|
||||
SimpleAllocator(SimpleAllocator &&from) noexcept :
|
||||
LinkedListNode(std::move(from)),
|
||||
_total_size(from._total_size),
|
||||
_max_size(from._max_size),
|
||||
_contiguous(from._contiguous),
|
||||
_lock(from._lock)
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
from._total_size = 0;
|
||||
from._max_size = 0;
|
||||
from._contiguous = 0;
|
||||
|
||||
// We still need to leave the list in a valid state.
|
||||
from._prev = &from;
|
||||
from._next = &from;
|
||||
|
||||
// Change all the blocks to point to the new allocator.
|
||||
LinkedListNode *next = _next;
|
||||
while (next != this) {
|
||||
SimpleAllocatorBlock *block = (SimpleAllocatorBlock *)next;
|
||||
nassertv(block->_allocator == &from);
|
||||
block->_allocator = this;
|
||||
|
||||
next = block->_next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -66,7 +97,7 @@ write(std::ostream &out) const {
|
||||
* Assumes the lock is already held.
|
||||
*/
|
||||
SimpleAllocatorBlock *SimpleAllocator::
|
||||
do_alloc(size_t size) {
|
||||
do_alloc(size_t size, size_t alignment) {
|
||||
if (size > _contiguous) {
|
||||
// Don't even bother.
|
||||
return nullptr;
|
||||
@ -86,9 +117,9 @@ do_alloc(size_t size) {
|
||||
// Scan until we have reached the last allocated block.
|
||||
while (block->_next != this) {
|
||||
SimpleAllocatorBlock *next = (SimpleAllocatorBlock *)block->_next;
|
||||
size_t free_size = next->_start - end;
|
||||
if (size <= free_size) {
|
||||
SimpleAllocatorBlock *new_block = make_block(end, size);
|
||||
size_t start = end + ((alignment - end) % alignment);
|
||||
if (start + size <= next->_start) {
|
||||
SimpleAllocatorBlock *new_block = make_block(start, size);
|
||||
nassertr(new_block->get_allocator() == this, nullptr);
|
||||
|
||||
new_block->insert_before(next);
|
||||
@ -103,6 +134,7 @@ do_alloc(size_t size) {
|
||||
}
|
||||
return new_block;
|
||||
}
|
||||
size_t free_size = next->_start - end;
|
||||
if (free_size > best) {
|
||||
best = free_size;
|
||||
}
|
||||
@ -113,9 +145,9 @@ do_alloc(size_t size) {
|
||||
}
|
||||
|
||||
// No free blocks; check for room at the end.
|
||||
size_t free_size = _max_size - end;
|
||||
if (size <= free_size) {
|
||||
SimpleAllocatorBlock *new_block = make_block(end, size);
|
||||
size_t start = end + ((alignment - end) % alignment);
|
||||
if (start + size <= _max_size) {
|
||||
SimpleAllocatorBlock *new_block = make_block(start, size);
|
||||
nassertr(new_block->get_allocator() == this, nullptr);
|
||||
|
||||
new_block->insert_before(this);
|
||||
@ -131,6 +163,7 @@ do_alloc(size_t size) {
|
||||
return new_block;
|
||||
}
|
||||
|
||||
size_t free_size = _max_size - end;
|
||||
if (free_size > best) {
|
||||
best = free_size;
|
||||
}
|
||||
|
@ -29,9 +29,10 @@ class SimpleAllocatorBlock;
|
||||
class EXPCL_PANDA_GOBJ SimpleAllocator : public LinkedListNode {
|
||||
PUBLISHED:
|
||||
INLINE explicit SimpleAllocator(size_t max_size, Mutex &lock);
|
||||
SimpleAllocator(SimpleAllocator &&from) noexcept;
|
||||
virtual ~SimpleAllocator();
|
||||
|
||||
INLINE SimpleAllocatorBlock *alloc(size_t size);
|
||||
INLINE SimpleAllocatorBlock *alloc(size_t size, size_t alignment=1);
|
||||
|
||||
INLINE bool is_empty() const;
|
||||
INLINE size_t get_total_size() const;
|
||||
@ -45,7 +46,7 @@ PUBLISHED:
|
||||
void write(std::ostream &out) const;
|
||||
|
||||
protected:
|
||||
SimpleAllocatorBlock *do_alloc(size_t size);
|
||||
SimpleAllocatorBlock *do_alloc(size_t size, size_t alignment=1);
|
||||
INLINE bool do_is_empty() const;
|
||||
|
||||
virtual SimpleAllocatorBlock *make_block(size_t start, size_t size);
|
||||
@ -91,6 +92,14 @@ protected:
|
||||
INLINE SimpleAllocatorBlock(SimpleAllocator *alloc,
|
||||
size_t start, size_t size);
|
||||
|
||||
public:
|
||||
SimpleAllocatorBlock() = default;
|
||||
SimpleAllocatorBlock(const SimpleAllocatorBlock ©) = delete;
|
||||
INLINE SimpleAllocatorBlock(SimpleAllocatorBlock &&from);
|
||||
|
||||
SimpleAllocatorBlock &operator = (const SimpleAllocatorBlock ©) = delete;
|
||||
INLINE SimpleAllocatorBlock &operator = (SimpleAllocatorBlock &&from);
|
||||
|
||||
PUBLISHED:
|
||||
INLINE ~SimpleAllocatorBlock();
|
||||
INLINE void free();
|
||||
@ -114,9 +123,9 @@ protected:
|
||||
INLINE bool do_realloc(size_t size);
|
||||
|
||||
private:
|
||||
SimpleAllocator *_allocator;
|
||||
size_t _start;
|
||||
size_t _size;
|
||||
SimpleAllocator *_allocator = nullptr;
|
||||
size_t _start = 0;
|
||||
size_t _size = 0;
|
||||
|
||||
friend class SimpleAllocator;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user