Skip to content

Commit

Permalink
[util] Changed my mind on allocator, switch to a polymorphic strategy
Browse files Browse the repository at this point in the history
fix: Change MemoryResource to be polymorphic
add: Allocator for adapting to std::allocator interface
fix: massively reduce dependencies.
  • Loading branch information
jd28 committed Oct 9, 2024
1 parent 2b853c7 commit ad12fe8
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 138 deletions.
1 change: 1 addition & 0 deletions lib/nw/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ add_library(nw STATIC
serialization/GffBuilder.cpp
serialization/Serialization.cpp

util/Allocator.cpp
util/base64.cpp
util/ByteArray.cpp
util/compression.cpp
Expand Down
9 changes: 4 additions & 5 deletions lib/nw/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,23 @@
#include ROLLNW_CUSTOM_CONFIGURATION_FILE
#else

#include "util/memory.hpp"
#include "util/Allocator.hpp"

#include <string>
#include <vector>

namespace nw {

// Strings.
// Strings
using String = std::string;
using StringView = std::string_view;
using PoolString = std::basic_string<char, std::char_traits<char>, PoolAllocator<char>>;
using ScopeString = std::basic_string<char, std::char_traits<char>, ScopeAllocator<char>>;
using PString = std::basic_string<char, std::char_traits<char>, Allocator<char>>;

// Vector
template <typename T>
using Vector = std::vector<T>;
template <typename T>
using ScopeVector = std::vector<T, ScopeAllocator<T>>;
using PVector = std::vector<T, Allocator<T>>;

} // namespace nw

Expand Down
23 changes: 23 additions & 0 deletions lib/nw/util/Allocator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "Allocator.hpp"
#include "memory.hpp"

namespace nw {
namespace detail {

MemoryResourceInternal::MemoryResourceInternal(MemoryResource* resource)
: resource_{resource}
{
}

void* MemoryResourceInternal::allocate(size_t bytes, size_t alignment)
{
return resource_->allocate(bytes, alignment);
}

void MemoryResourceInternal::deallocate(void* p, size_t bytes, size_t alignment)
{
resource_->deallocate(p, bytes, alignment);
}

} // namespace detail
} // namespace nw
68 changes: 68 additions & 0 deletions lib/nw/util/Allocator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#pragma once

#include <stddef.h>

namespace nw {

struct MemoryResource;

namespace detail {
// Hide MemoryResource impl details
struct MemoryResourceInternal {
MemoryResourceInternal(MemoryResource* resoure);
void* allocate(size_t nbytes, size_t alignment = alignof(max_align_t));
void deallocate(void* p, size_t bytes, size_t alignment = alignof(max_align_t));
MemoryResource* resource_;
};

}

/// Allocator adapter for MemoryResource, so this is a polymorphic allocator.
template <typename T>
class Allocator {
public:
using value_type = T;

Allocator(MemoryResource* resource)
: resource_(resource)
{
}

template <typename U>
Allocator(const Allocator<U>& other) noexcept
: resource_(other.resource_)
{
}

T* allocate(size_t n)
{
if (n == 0) { return nullptr; }
return static_cast<T*>(resource_.allocate(n * sizeof(T), alignof(T)));
}

void deallocate(T* ptr, size_t size) noexcept
{
resource_.deallocate(ptr, size);
}

template <typename U>
struct rebind {
using other = Allocator<U>;
};

// private:
detail::MemoryResourceInternal resource_;
};

template <typename T, typename U>
bool operator==(const Allocator<T>& a, const Allocator<U>& b) noexcept
{
return &a.resource_.resource_ == &b.resource_.resource_;
}

template <typename T, typename U>
bool operator!=(const Allocator<T>& a, const Allocator<U>& b) noexcept
{
return !(a == b);
}
} // namespace nw
4 changes: 2 additions & 2 deletions lib/nw/util/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ MemoryScope::~MemoryScope()
arena_->rewind(marker_);
}

void* MemoryScope::alloc(size_t size, size_t alignment)
void* MemoryScope::allocate(size_t size, size_t alignment)
{
return arena_->allocate(size, alignment);
}
Expand Down Expand Up @@ -240,7 +240,7 @@ void* MemoryPool::allocate(size_t size, size_t alignment)
return aligned;
}

void MemoryPool::deallocate(void* ptr)
void MemoryPool::deallocate(void* ptr, size_t, size_t)
{
if (!ptr) return;
detail::PoolHeader* header = reinterpret_cast<detail::PoolHeader*>(static_cast<char*>(ptr) - sizeof(detail::PoolHeader));
Expand Down
Loading

0 comments on commit ad12fe8

Please sign in to comment.