More work on asl::box
This commit is contained in:
14
MODULE.bazel.lock
generated
14
MODULE.bazel.lock
generated
@ -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": {},
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -7,7 +7,8 @@ namespace asl
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
concept allocator = requires(T& alloc, layout layout, void* ptr)
|
||||
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*>;
|
||||
|
83
asl/box.hpp
83
asl/box.hpp
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user