From d241eaf1b209dcfb05656842dd6250067b704d99 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Tue, 19 Nov 2024 00:08:33 +0100 Subject: Add allocator, start work on box --- asl/BUILD.bazel | 4 ++++ asl/allocator.cpp | 38 ++++++++++++++++++++++++++++++++++++++ asl/allocator.hpp | 28 ++++++++++++++++++++++++++++ asl/box.hpp | 19 +++++++++++++++++++ asl/format.cpp | 28 ++++++++++++++-------------- asl/format.hpp | 44 ++++++++++++++++++++++---------------------- asl/io.hpp | 8 ++++---- asl/layout.hpp | 6 ++++++ asl/memory.hpp | 5 +++++ asl/meta.hpp | 6 +++--- asl/print.cpp | 6 +++--- asl/print.hpp | 4 ++-- asl/tests/box_tests.cpp | 6 ++++++ asl/tests/format_tests.cpp | 23 +++++++++++------------ asl/tests/meta_tests.cpp | 1 + asl/utility.hpp | 6 ++++++ 16 files changed, 172 insertions(+), 60 deletions(-) create mode 100644 asl/allocator.cpp create mode 100644 asl/allocator.hpp create mode 100644 asl/box.hpp create mode 100644 asl/tests/box_tests.cpp (limited to 'asl') diff --git a/asl/BUILD.bazel b/asl/BUILD.bazel index 0841a86..20a1651 100644 --- a/asl/BUILD.bazel +++ b/asl/BUILD.bazel @@ -1,8 +1,10 @@ cc_library( name = "asl", hdrs = [ + "allocator.hpp", "annotations.hpp", "assert.hpp", + "box.hpp", "config.hpp", "format.hpp", "functional.hpp", @@ -19,6 +21,7 @@ cc_library( "utility.hpp", ], srcs = [ + "allocator.cpp", "format.cpp", "print.cpp", ], @@ -36,6 +39,7 @@ cc_library( "//asl/testing", ], ) for name in [ + "box", "format", "functional", "integers", diff --git a/asl/allocator.cpp b/asl/allocator.cpp new file mode 100644 index 0000000..9559637 --- /dev/null +++ b/asl/allocator.cpp @@ -0,0 +1,38 @@ +#include "asl/allocator.hpp" +#include "asl/assert.hpp" +#include "asl/utility.hpp" +#include "asl/memory.hpp" + +#include + +// @Todo zalloc +// @Todo Cookies +// @Todo Debug values + +void* asl::GlobalHeap::alloc(const layout& layout) +{ + void* ptr = ::_aligned_malloc( + static_cast(layout.size), + static_cast(layout.align)); + ASL_ASSERT(ptr != nullptr); // @Todo panic + return ptr; +} + +void* asl::GlobalHeap::realloc(void* old_ptr, const layout& old_layout, const layout& new_layout) +{ + if (new_layout.align <= old_layout.align) + { + void* new_ptr = ::realloc(old_ptr, static_cast(new_layout.size)); + ASL_ASSERT(new_ptr != nullptr); // @Todo panic + return new_ptr; + } + + void* new_ptr = alloc(new_layout); + asl::memcpy(new_ptr, old_ptr, asl::min(old_layout.size, new_layout.size)); + return new_ptr; +} + +void asl::GlobalHeap::dealloc(void* ptr, const layout&) +{ + ::free(ptr); +} diff --git a/asl/allocator.hpp b/asl/allocator.hpp new file mode 100644 index 0000000..b6c1a9a --- /dev/null +++ b/asl/allocator.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "asl/layout.hpp" +#include "asl/meta.hpp" + +namespace asl +{ + +template +concept allocator = requires(T& alloc, layout layout, void* ptr) +{ + { alloc.alloc(layout) } -> same_as; + { alloc.realloc(ptr, layout, layout) } -> same_as; + alloc.dealloc(ptr, layout); +}; + +class GlobalHeap +{ +public: + static void* alloc(const layout&); + static void* realloc(void* ptr, const layout& old, const layout& new_layout); + static void dealloc(void* ptr, const layout&); +}; +static_assert(allocator); + +using DefaultAllocator = GlobalHeap; + +} // namespace asl diff --git a/asl/box.hpp b/asl/box.hpp new file mode 100644 index 0000000..0cab66b --- /dev/null +++ b/asl/box.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "asl/allocator.hpp" +#include "asl/annotations.hpp" + +namespace asl +{ + +template +class box +{ + T* m_ptr; + ASL_NO_UNIQUE_ADDRESS Allocator m_alloc; + +public: +}; + +} // namespace asl + diff --git a/asl/format.cpp b/asl/format.cpp index d25bade..461fc77 100644 --- a/asl/format.cpp +++ b/asl/format.cpp @@ -4,11 +4,11 @@ #include "asl/memory.hpp" void asl::format_internals::format( - writer* writer, + Writer* writer, string_view fmt, span args) { - formatter f(writer); + Formatter f(writer); const auto* arg_it = args.begin(); const auto* arg_end = args.end(); @@ -74,22 +74,22 @@ void asl::format_internals::format( f.write(fmt); } -void asl::AslFormat(formatter& f, const char* str) +void asl::AslFormat(Formatter& f, const char* str) { f.write({str, asl::strlen(str)}); } -void asl::AslFormat(formatter& f, float) +void asl::AslFormat(Formatter& f, float) { f.write(""); // @Todo Float formatting } -void asl::AslFormat(formatter& f, double) +void asl::AslFormat(Formatter& f, double) { f.write(""); // @Todo Float formatting } -void asl::AslFormat(formatter& f, bool v) +void asl::AslFormat(Formatter& f, bool v) { if (v) { @@ -101,22 +101,22 @@ void asl::AslFormat(formatter& f, bool v) } } -void asl::AslFormat(formatter& f, uint8_t v) +void asl::AslFormat(Formatter& f, uint8_t v) { AslFormat(f, static_cast(v)); } -void asl::AslFormat(formatter& f, uint16_t v) +void asl::AslFormat(Formatter& f, uint16_t v) { AslFormat(f, static_cast(v)); } -void asl::AslFormat(formatter& f, uint32_t v) +void asl::AslFormat(Formatter& f, uint32_t v) { AslFormat(f, static_cast(v)); } -void asl::AslFormat(formatter& f, uint64_t v) +void asl::AslFormat(Formatter& f, uint64_t v) { static constexpr char s_pairs_storage[] = { '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', @@ -180,22 +180,22 @@ void asl::AslFormat(formatter& f, uint64_t v) f.write(string_view(buffer, kMaxDigits).substr(cursor)); } -void asl::AslFormat(formatter& f, int8_t v) +void asl::AslFormat(Formatter& f, int8_t v) { AslFormat(f, static_cast(v)); } -void asl::AslFormat(formatter& f, int16_t v) +void asl::AslFormat(Formatter& f, int16_t v) { AslFormat(f, static_cast(v)); } -void asl::AslFormat(formatter& f, int32_t v) +void asl::AslFormat(Formatter& f, int32_t v) { AslFormat(f, static_cast(v)); } -void asl::AslFormat(formatter& f, int64_t v) +void asl::AslFormat(Formatter& f, int64_t v) { if (v < 0) { diff --git a/asl/format.hpp b/asl/format.hpp index 57be45d..7cf3917 100644 --- a/asl/format.hpp +++ b/asl/format.hpp @@ -9,10 +9,10 @@ namespace asl { -class formatter; +class Formatter; template -concept formattable = requires (formatter& f, const T& value) +concept formattable = requires (Formatter& f, const T& value) { AslFormat(f, value); }; @@ -23,10 +23,10 @@ namespace format_internals struct type_erased_arg { const void* data; - void (*fn)(formatter&, const void*); + void (*fn)(Formatter&, const void*); template - static constexpr void erased_fn(formatter& f, const void* data) + static constexpr void erased_fn(Formatter& f, const void* data) { AslFormat(f, *reinterpret_cast(data)); } @@ -38,16 +38,16 @@ struct type_erased_arg {} }; -void format(writer*, string_view fmt, span args); +void format(Writer*, string_view fmt, span args); } // namespace internals -class formatter +class Formatter { - writer* m_writer; + Writer* m_writer; public: - explicit constexpr formatter(writer* writer) + explicit constexpr Formatter(Writer* writer) : m_writer{writer} {} @@ -58,7 +58,7 @@ public: }; template -void format(writer* w, string_view fmt, const Args&... args) +void format(Writer* w, string_view fmt, const Args&... args) { if constexpr (types_count > 0) { @@ -75,26 +75,26 @@ void format(writer* w, string_view fmt, const Args&... args) } template -void AslFormat(formatter& f, const char (&str)[N]) +void AslFormat(Formatter& f, const char (&str)[N]) { f.write(str, N - 1); } -void AslFormat(formatter& f, const char* str); +void AslFormat(Formatter& f, const char* str); -void AslFormat(formatter& f, float); -void AslFormat(formatter& f, double); +void AslFormat(Formatter& f, float); +void AslFormat(Formatter& f, double); -void AslFormat(formatter& f, bool); +void AslFormat(Formatter& f, bool); -void AslFormat(formatter& f, uint8_t); -void AslFormat(formatter& f, uint16_t); -void AslFormat(formatter& f, uint32_t); -void AslFormat(formatter& f, uint64_t); +void AslFormat(Formatter& f, uint8_t); +void AslFormat(Formatter& f, uint16_t); +void AslFormat(Formatter& f, uint32_t); +void AslFormat(Formatter& f, uint64_t); -void AslFormat(formatter& f, int8_t); -void AslFormat(formatter& f, int16_t); -void AslFormat(formatter& f, int32_t); -void AslFormat(formatter& f, int64_t); +void AslFormat(Formatter& f, int8_t); +void AslFormat(Formatter& f, int16_t); +void AslFormat(Formatter& f, int32_t); +void AslFormat(Formatter& f, int64_t); } // namespace asl diff --git a/asl/io.hpp b/asl/io.hpp index 9c45624..e54f00c 100644 --- a/asl/io.hpp +++ b/asl/io.hpp @@ -7,12 +7,12 @@ namespace asl { -class writer +class Writer { public: - writer() = default; - ASL_DELETE_COPY_MOVE(writer); - virtual ~writer() = default; + Writer() = default; + ASL_DELETE_COPY_MOVE(Writer); + virtual ~Writer() = default; virtual void write(span) = 0; }; diff --git a/asl/layout.hpp b/asl/layout.hpp index 06fbe10..2295a1c 100644 --- a/asl/layout.hpp +++ b/asl/layout.hpp @@ -24,6 +24,12 @@ struct layout { return layout{ size_of, align_of }; } + + template + static constexpr layout array(isize_t size) + { + return layout{ size_of * size, align_of }; + } }; } // namespace asl diff --git a/asl/memory.hpp b/asl/memory.hpp index 33b10fe..23aa392 100644 --- a/asl/memory.hpp +++ b/asl/memory.hpp @@ -15,6 +15,11 @@ constexpr isize_t memcmp(const void* a, const void* b, isize_t size) return __builtin_memcmp(a, b, static_cast(size)); } +constexpr void memcpy(void* dst, const void* src, isize_t size) +{ + __builtin_memcpy(dst, src, static_cast(size)); +} + constexpr isize_t strlen(const char* s) { return static_cast(__builtin_strlen(s)); diff --git a/asl/meta.hpp b/asl/meta.hpp index e64b4f2..552bf0c 100644 --- a/asl/meta.hpp +++ b/asl/meta.hpp @@ -21,10 +21,10 @@ template struct _select_helper template using select_t = _select_helper::type; -template struct _is_same_helper : false_type {}; -template struct _is_same_helper : true_type {}; +template struct _same_as_helper : false_type {}; +template struct _same_as_helper : true_type {}; -template concept same_as = _is_same_helper::value && _is_same_helper::value; +template concept same_as = _same_as_helper::value && _same_as_helper::value; template auto _as_lref_helper(int) -> id; template auto _as_lref_helper(...) -> id; diff --git a/asl/print.cpp b/asl/print.cpp index 6f81f19..17f00c8 100644 --- a/asl/print.cpp +++ b/asl/print.cpp @@ -3,7 +3,7 @@ #include // @Todo Optimize this, maybe make buffered -class ConsoleWriter : public asl::writer +class ConsoleWriter : public asl::Writer { FILE* m_handle; @@ -18,13 +18,13 @@ public: } }; -asl::writer* asl::print_internals::get_stdout_writer() +asl::Writer* asl::print_internals::get_stdout_writer() { static ConsoleWriter s_writer{stdout}; return &s_writer; } -asl::writer* asl::print_internals::get_stderr_writer() +asl::Writer* asl::print_internals::get_stderr_writer() { static ConsoleWriter s_writer{stderr}; return &s_writer; diff --git a/asl/print.hpp b/asl/print.hpp index 4e7d07a..208bcb2 100644 --- a/asl/print.hpp +++ b/asl/print.hpp @@ -9,8 +9,8 @@ namespace print_internals { // @Todo Make print writers thread safe -writer* get_stdout_writer(); -writer* get_stderr_writer(); +Writer* get_stdout_writer(); +Writer* get_stderr_writer(); } // namespace print_internals diff --git a/asl/tests/box_tests.cpp b/asl/tests/box_tests.cpp new file mode 100644 index 0000000..6c4d543 --- /dev/null +++ b/asl/tests/box_tests.cpp @@ -0,0 +1,6 @@ +#include "asl/box.hpp" + +#include "asl/testing/testing.hpp" + +static_assert(sizeof(asl::box) == sizeof(int*)); + diff --git a/asl/tests/format_tests.cpp b/asl/tests/format_tests.cpp index cb7a13f..a8c1ad6 100644 --- a/asl/tests/format_tests.cpp +++ b/asl/tests/format_tests.cpp @@ -1,26 +1,25 @@ #include "asl/format.hpp" #include "asl/testing/testing.hpp" -#include "asl/print.hpp" - -#include -#include -#include -#include - -// @Todo Improve this to use our utilities, not the C stdlib +#include "asl/allocator.hpp" static_assert(asl::formattable); -class StringSink : public asl::writer +class StringSink : public asl::Writer { + // @Todo Use string, once we have it, or a buffer isize_t m_current_len{}; char* m_data{}; public: void write(asl::span str) override { - m_data = (char*)realloc(m_data, (size_t)(m_current_len + str.size())); - memcpy(m_data + m_current_len, str.data(), (size_t)str.size()); + m_data = reinterpret_cast(asl::GlobalHeap::realloc( + m_data, + asl::layout::array(m_current_len), + asl::layout::array(m_current_len + str.size()))); + + asl::memcpy(m_data + m_current_len, str.data(), str.size()); + m_current_len += str.size(); } @@ -29,7 +28,7 @@ public: void reset() { m_current_len = 0; - free(m_data); + asl::GlobalHeap::dealloc(m_data, asl::layout::array(m_current_len)); m_data = nullptr; } }; diff --git a/asl/tests/meta_tests.cpp b/asl/tests/meta_tests.cpp index 40b9046..354cea6 100644 --- a/asl/tests/meta_tests.cpp +++ b/asl/tests/meta_tests.cpp @@ -35,6 +35,7 @@ static_assert(!asl::trivially_copy_constructible); static_assert(asl::move_constructible); static_assert(asl::move_constructible); static_assert(asl::move_constructible); +static_assert(asl::move_constructible); static_assert(!asl::move_constructible); static_assert(asl::trivially_move_constructible); diff --git a/asl/utility.hpp b/asl/utility.hpp index d54d965..7740eff 100644 --- a/asl/utility.hpp +++ b/asl/utility.hpp @@ -24,6 +24,12 @@ constexpr U bit_cast(T value) requires (size_of == size_of) return __builtin_bit_cast(U, value); } +template +T min(T a, T b) +{ + return (a <= b) ? a : b; +} + #define ASL_DELETE_COPY(T) \ T(const T&) = delete; \ T& operator=(const T&) = delete; -- cgit