More work on asl::box

This commit is contained in:
2024-11-19 23:30:55 +01:00
parent 3bddc19f58
commit f5ef1937ea
6 changed files with 166 additions and 13 deletions

14
MODULE.bazel.lock generated
View File

@ -64,20 +64,20 @@
"@@apple_support~//crosstool:setup.bzl%apple_cc_configure_extension": {
"general": {
"bzlTransitiveDigest": "PjIds3feoYE8SGbbIq2SFTZy3zmxeO2tQevJZNDo7iY=",
"usagesDigest": "aLmqbvowmHkkBPve05yyDNGN7oh7QE9kBADr3QIZTZs=",
"usagesDigest": "+hz7IHWN6A1oVJJWNDB6yZRG+RYhF76wAYItpAeIUIg=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {
"local_config_apple_cc": {
"bzlFile": "@@apple_support~//crosstool:setup.bzl",
"ruleClassName": "_apple_cc_autoconf",
"attributes": {}
},
"local_config_apple_cc_toolchains": {
"bzlFile": "@@apple_support~//crosstool:setup.bzl",
"ruleClassName": "_apple_cc_autoconf_toolchains",
"attributes": {}
},
"local_config_apple_cc": {
"bzlFile": "@@apple_support~//crosstool:setup.bzl",
"ruleClassName": "_apple_cc_autoconf",
"attributes": {}
}
},
"recordedRepoMappingEntries": [
@ -92,7 +92,7 @@
"@@platforms//host:extension.bzl%host_platform": {
"general": {
"bzlTransitiveDigest": "xelQcPZH8+tmuOHVjL9vDxMnnQNMlwj0SlvgoqBkm4U=",
"usagesDigest": "meSzxn3DUCcYEhq4HQwExWkWtU4EjriRBQLsZN+Q0SU=",
"usagesDigest": "pCYpDQmqMbmiiPI1p2Kd3VLm5T48rRAht5WdW0X2GlA=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},

View File

@ -26,6 +26,11 @@ void* asl::GlobalHeap::alloc(const layout& layout)
void* asl::GlobalHeap::realloc(void* old_ptr, const layout& old_layout, const layout& new_layout)
{
#if ASL_OS_WINDOWS
return ::_aligned_realloc(old_ptr,
static_cast<size_t>(new_layout.size),
static_cast<size_t>(new_layout.align));
#elif ASL_OS_LINUX
if (new_layout.align <= old_layout.align)
{
void* new_ptr = ::realloc(old_ptr, static_cast<size_t>(new_layout.size));
@ -36,9 +41,14 @@ void* asl::GlobalHeap::realloc(void* old_ptr, const layout& old_layout, const la
void* new_ptr = alloc(new_layout);
asl::memcpy(new_ptr, old_ptr, asl::min(old_layout.size, new_layout.size));
return new_ptr;
#endif
}
void asl::GlobalHeap::dealloc(void* ptr, const layout&)
{
#if ASL_OS_WINDOWS
::_aligned_free(ptr);
#elif ASL_OS_LINUX
::free(ptr);
#endif
}

View File

@ -7,12 +7,13 @@ namespace asl
{
template<typename T>
concept allocator = requires(T& alloc, layout layout, void* ptr)
{
{ alloc.alloc(layout) } -> same_as<void*>;
{ alloc.realloc(ptr, layout, layout) } -> same_as<void*>;
alloc.dealloc(ptr, layout);
};
concept allocator = moveable<T> &&
requires(T& alloc, layout layout, void* ptr)
{
{ alloc.alloc(layout) } -> same_as<void*>;
{ alloc.realloc(ptr, layout, layout) } -> same_as<void*>;
alloc.dealloc(ptr, layout);
};
class GlobalHeap
{

View File

@ -1,7 +1,10 @@
#pragma once
#include "asl/allocator.hpp"
#include "asl/assert.hpp"
#include "asl/annotations.hpp"
#include "asl/memory.hpp"
#include "asl/utility.hpp"
namespace asl
{
@ -13,7 +16,87 @@ class box
ASL_NO_UNIQUE_ADDRESS Allocator m_alloc;
public:
explicit constexpr box(T* ptr = nullptr)
requires default_constructible<Allocator>
: m_ptr{ptr}
{}
constexpr box(T* ptr, Allocator alloc)
: m_ptr{ptr}
, m_alloc{ASL_MOVE(alloc)}
{}
constexpr box(box&& other)
: m_ptr{exchange(other.m_ptr, nullptr)}
, m_alloc{ASL_MOVE(other.m_alloc)}
{}
constexpr box& operator=(box&& other)
{
if (this == &other) { return *this; }
if (m_ptr != nullptr) { reset(); }
m_ptr = exchange(other.m_ptr, nullptr);
m_alloc = ASL_MOVE(other.m_alloc);
return *this;
}
box(const box&) = delete;
box& operator=(const box&) = delete;
constexpr ~box()
{
reset();
}
constexpr void reset()
{
if (m_ptr != nullptr)
{
if constexpr (!trivially_destructible<T>)
{
m_ptr->~T();
}
m_alloc.dealloc(m_ptr, layout::of<T>());
m_ptr = nullptr;
}
}
constexpr T* get() const { return m_ptr; }
constexpr T& operator*() const
{
ASL_ASSERT(m_ptr != nullptr);
return *m_ptr;
}
constexpr T* operator->() const
{
ASL_ASSERT(m_ptr != nullptr);
return m_ptr;
}
};
template<is_object T, allocator Allocator = DefaultAllocator, typename... Args>
constexpr box<T, Allocator> make_box_in(Allocator allocator, Args&&... args)
requires constructible_from<T, Args&&...>
{
void* raw_ptr = allocator.alloc(layout::of<T>());
T* ptr = new (raw_ptr) T(ASL_FWD(args)...);
return box(ptr, ASL_MOVE(allocator));
}
template<is_object T, allocator Allocator = DefaultAllocator, typename... Args>
constexpr box<T, Allocator> make_box(Args&&... args)
requires default_constructible<Allocator> && constructible_from<T, Args&&...>
{
Allocator allocator{};
void* raw_ptr = allocator.alloc(layout::of<T>());
T* ptr = new (raw_ptr) T{ ASL_FWD(args)... };
return box<T>(ptr, ASL_MOVE(allocator));
}
} // namespace asl

View File

@ -69,6 +69,9 @@ template<typename T> concept trivially_destructible = __is_trivially_destructibl
template<typename T> concept trivially_copyable = __is_trivially_copyable(T);
template<typename T> concept copyable = copy_constructible<T> && copy_assignable<T>;
template<typename T> concept moveable = move_constructible<T> && move_assignable<T>;
template<typename To, typename From>
concept convertible_from = __is_convertible(From, To);

View File

@ -1,6 +1,62 @@
#include "asl/box.hpp"
#include "asl/testing/testing.hpp"
#include "asl/tests/test_types.hpp"
static_assert(sizeof(asl::box<int>) == sizeof(int*));
static_assert(asl::default_constructible<asl::box<int>>);
static_assert(!asl::copyable<asl::box<int>>);
static_assert(asl::moveable<asl::box<int>>);
static_assert(asl::default_constructible<asl::box<NonMoveConstructible>>);
ASL_TEST(destructor)
{
bool d = false;
{
asl::box<DestructorObserver> box2;
{
auto box = asl::make_box<DestructorObserver>(&d);
ASL_TEST_ASSERT(!d);
auto box3 = ASL_MOVE(box);
ASL_TEST_ASSERT(!d);
box2 = ASL_MOVE(box3);
ASL_TEST_ASSERT(!d);
}
ASL_TEST_ASSERT(!d);
}
ASL_TEST_ASSERT(d);
}
ASL_TEST(value)
{
auto b = asl::make_box<int>(24);
ASL_TEST_EXPECT(*b == 24);
auto b2 = ASL_MOVE(b);
ASL_TEST_EXPECT(*b2 == 24);
}
ASL_TEST(ptr)
{
auto b = asl::make_box<int>(24);
auto* ptr1 = b.get();
auto b2 = ASL_MOVE(b);
auto* ptr2 = b2.get();
ASL_TEST_EXPECT(ptr1 == ptr2);
}
struct Struct { int a; };
ASL_TEST(arrow)
{
auto b = asl::make_box<Struct>(45);
ASL_TEST_EXPECT(b->a == 45);
}