diff options
Diffstat (limited to 'thirdparty/tourist/foundation/src/allocator.cpp')
| -rw-r--r-- | thirdparty/tourist/foundation/src/allocator.cpp | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/thirdparty/tourist/foundation/src/allocator.cpp b/thirdparty/tourist/foundation/src/allocator.cpp new file mode 100644 index 000000000..c6f021ad2 --- /dev/null +++ b/thirdparty/tourist/foundation/src/allocator.cpp @@ -0,0 +1,69 @@ +#include <foundation/buffer.h> +#include <foundation/malloc.h> + +#include "slab.h" + +//------------------------------------------------------------------------------ +Allocator::~Allocator() +{ + if (_slab != nullptr) + _slab->dec_ref(); +} + +//------------------------------------------------------------------------------ +MutableBuffer Allocator::create_buffer(uint32 size) +{ + auto create_slab = [this] (uint32 slab_size) { + auto* slab = tt_malloc<Slab>(slab_size + sizeof(Slab)); + slab->_allocator = this; + slab->_size = slab_size; + slab->_refs.store_relaxed(0); + return slab; + }; + + enum { + PACKET_PAGE_SIZE = 4 << 10, + PACKET_SLAB_SIZE = 1 << 20, + PACKET_ALIGN = 32 - 1, + }; + + if (size > PACKET_PAGE_SIZE) + { + Slab* slab = create_slab(size); + return MutableBuffer(slab, size, 0); + } + + uint32 alloc_size = (size + PACKET_ALIGN) & ~PACKET_ALIGN; + + UniqueLock _(_lock); + + if (alloc_size > _slab_free && _slab != nullptr) + { + _slab->dec_ref(); + _slab = nullptr; + } + + if (_slab == nullptr) + { + _slab_free = PACKET_SLAB_SIZE; + _slab = create_slab(_slab_free); + _slab->inc_ref(); + } + + uint32 offset = PACKET_SLAB_SIZE - _slab_free; + _slab_free -= alloc_size; + return MutableBuffer(_slab, size, offset); +} + +//------------------------------------------------------------------------------ +void Allocator::free_slab(Slab* slab) +{ + tt_free(slab); +} + +//------------------------------------------------------------------------------ +Allocator& Allocator::get_from(Buffer& buffer) { return get_from(buffer._slab); } +Allocator& Allocator::get_from(BufferRef& ref) { return get_from(ref.get_slab()); } +Allocator& Allocator::get_from(BufferStream& stream){ return get_from(stream.get_slab()); } +Allocator& Allocator::get_from(Pointer& pointer) { return get_from(pointer.get_slab()); } +Allocator& Allocator::get_from(const Slab* slab) { return slab->get_allocator(); } |