aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/tourist/foundation/src/allocator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/tourist/foundation/src/allocator.cpp')
-rw-r--r--thirdparty/tourist/foundation/src/allocator.cpp69
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(); }