Add allocator, start work on box
This commit is contained in:
@ -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",
|
||||
|
38
asl/allocator.cpp
Normal file
38
asl/allocator.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include "asl/allocator.hpp"
|
||||
#include "asl/assert.hpp"
|
||||
#include "asl/utility.hpp"
|
||||
#include "asl/memory.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
// @Todo zalloc
|
||||
// @Todo Cookies
|
||||
// @Todo Debug values
|
||||
|
||||
void* asl::GlobalHeap::alloc(const layout& layout)
|
||||
{
|
||||
void* ptr = ::_aligned_malloc(
|
||||
static_cast<size_t>(layout.size),
|
||||
static_cast<size_t>(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<size_t>(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);
|
||||
}
|
28
asl/allocator.hpp
Normal file
28
asl/allocator.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "asl/layout.hpp"
|
||||
#include "asl/meta.hpp"
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
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<GlobalHeap>);
|
||||
|
||||
using DefaultAllocator = GlobalHeap;
|
||||
|
||||
} // namespace asl
|
19
asl/box.hpp
Normal file
19
asl/box.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "asl/allocator.hpp"
|
||||
#include "asl/annotations.hpp"
|
||||
|
||||
namespace asl
|
||||
{
|
||||
|
||||
template<is_object T, allocator Allocator = DefaultAllocator>
|
||||
class box
|
||||
{
|
||||
T* m_ptr;
|
||||
ASL_NO_UNIQUE_ADDRESS Allocator m_alloc;
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
} // namespace asl
|
||||
|
@ -4,11 +4,11 @@
|
||||
#include "asl/memory.hpp"
|
||||
|
||||
void asl::format_internals::format(
|
||||
writer* writer,
|
||||
Writer* writer,
|
||||
string_view fmt,
|
||||
span<const type_erased_arg> 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("<FLOAT>"); // @Todo Float formatting
|
||||
}
|
||||
|
||||
void asl::AslFormat(formatter& f, double)
|
||||
void asl::AslFormat(Formatter& f, double)
|
||||
{
|
||||
f.write("<DOUBLE>"); // @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<uint64_t>(v));
|
||||
}
|
||||
|
||||
void asl::AslFormat(formatter& f, uint16_t v)
|
||||
void asl::AslFormat(Formatter& f, uint16_t v)
|
||||
{
|
||||
AslFormat(f, static_cast<uint64_t>(v));
|
||||
}
|
||||
|
||||
void asl::AslFormat(formatter& f, uint32_t v)
|
||||
void asl::AslFormat(Formatter& f, uint32_t v)
|
||||
{
|
||||
AslFormat(f, static_cast<uint64_t>(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<int64_t>(v));
|
||||
}
|
||||
|
||||
void asl::AslFormat(formatter& f, int16_t v)
|
||||
void asl::AslFormat(Formatter& f, int16_t v)
|
||||
{
|
||||
AslFormat(f, static_cast<int64_t>(v));
|
||||
}
|
||||
|
||||
void asl::AslFormat(formatter& f, int32_t v)
|
||||
void asl::AslFormat(Formatter& f, int32_t v)
|
||||
{
|
||||
AslFormat(f, static_cast<int64_t>(v));
|
||||
}
|
||||
|
||||
void asl::AslFormat(formatter& f, int64_t v)
|
||||
void asl::AslFormat(Formatter& f, int64_t v)
|
||||
{
|
||||
if (v < 0)
|
||||
{
|
||||
|
@ -9,10 +9,10 @@
|
||||
namespace asl
|
||||
{
|
||||
|
||||
class formatter;
|
||||
class Formatter;
|
||||
|
||||
template<typename T>
|
||||
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<formattable T>
|
||||
static constexpr void erased_fn(formatter& f, const void* data)
|
||||
static constexpr void erased_fn(Formatter& f, const void* data)
|
||||
{
|
||||
AslFormat(f, *reinterpret_cast<const T*>(data));
|
||||
}
|
||||
@ -38,16 +38,16 @@ struct type_erased_arg
|
||||
{}
|
||||
};
|
||||
|
||||
void format(writer*, string_view fmt, span<const type_erased_arg> args);
|
||||
void format(Writer*, string_view fmt, span<const type_erased_arg> 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<formattable... Args>
|
||||
void format(writer* w, string_view fmt, const Args&... args)
|
||||
void format(Writer* w, string_view fmt, const Args&... args)
|
||||
{
|
||||
if constexpr (types_count<Args...> > 0)
|
||||
{
|
||||
@ -75,26 +75,26 @@ void format(writer* w, string_view fmt, const Args&... args)
|
||||
}
|
||||
|
||||
template<isize_t N>
|
||||
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
|
||||
|
@ -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<const byte>) = 0;
|
||||
};
|
||||
|
@ -24,6 +24,12 @@ struct layout
|
||||
{
|
||||
return layout{ size_of<T>, align_of<T> };
|
||||
}
|
||||
|
||||
template<is_object T>
|
||||
static constexpr layout array(isize_t size)
|
||||
{
|
||||
return layout{ size_of<T> * size, align_of<T> };
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace asl
|
||||
|
@ -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_t>(size));
|
||||
}
|
||||
|
||||
constexpr void memcpy(void* dst, const void* src, isize_t size)
|
||||
{
|
||||
__builtin_memcpy(dst, src, static_cast<size_t>(size));
|
||||
}
|
||||
|
||||
constexpr isize_t strlen(const char* s)
|
||||
{
|
||||
return static_cast<isize_t>(__builtin_strlen(s));
|
||||
|
@ -21,10 +21,10 @@ template<typename U, typename V> struct _select_helper<true, U, V>
|
||||
|
||||
template<bool kSelect, typename U, typename V> using select_t = _select_helper<kSelect, U, V>::type;
|
||||
|
||||
template<typename U, typename V> struct _is_same_helper : false_type {};
|
||||
template<typename T> struct _is_same_helper<T, T> : true_type {};
|
||||
template<typename U, typename V> struct _same_as_helper : false_type {};
|
||||
template<typename T> struct _same_as_helper<T, T> : true_type {};
|
||||
|
||||
template<typename U, typename V> concept same_as = _is_same_helper<U, V>::value && _is_same_helper<V, U>::value;
|
||||
template<typename U, typename V> concept same_as = _same_as_helper<U, V>::value && _same_as_helper<V, U>::value;
|
||||
|
||||
template<typename T> auto _as_lref_helper(int) -> id<T&>;
|
||||
template<typename T> auto _as_lref_helper(...) -> id<T>;
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <cstdio>
|
||||
|
||||
// @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;
|
||||
|
@ -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
|
||||
|
||||
|
6
asl/tests/box_tests.cpp
Normal file
6
asl/tests/box_tests.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "asl/box.hpp"
|
||||
|
||||
#include "asl/testing/testing.hpp"
|
||||
|
||||
static_assert(sizeof(asl::box<int>) == sizeof(int*));
|
||||
|
@ -1,26 +1,25 @@
|
||||
#include "asl/format.hpp"
|
||||
#include "asl/testing/testing.hpp"
|
||||
#include "asl/print.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
|
||||
// @Todo Improve this to use our utilities, not the C stdlib
|
||||
#include "asl/allocator.hpp"
|
||||
|
||||
static_assert(asl::formattable<decltype("Hello")>);
|
||||
|
||||
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<const asl::byte> 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<char*>(asl::GlobalHeap::realloc(
|
||||
m_data,
|
||||
asl::layout::array<char>(m_current_len),
|
||||
asl::layout::array<char>(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<char>(m_current_len));
|
||||
m_data = nullptr;
|
||||
}
|
||||
};
|
||||
|
@ -35,6 +35,7 @@ static_assert(!asl::trivially_copy_constructible<NonCopyConstructible>);
|
||||
static_assert(asl::move_constructible<int>);
|
||||
static_assert(asl::move_constructible<TriviallyMoveConstructible>);
|
||||
static_assert(asl::move_constructible<MoveConstructible>);
|
||||
static_assert(asl::move_constructible<CopyConstructible>);
|
||||
static_assert(!asl::move_constructible<NonMoveConstructible>);
|
||||
|
||||
static_assert(asl::trivially_move_constructible<int>);
|
||||
|
@ -24,6 +24,12 @@ constexpr U bit_cast(T value) requires (size_of<T> == size_of<U>)
|
||||
return __builtin_bit_cast(U, value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
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;
|
||||
|
Reference in New Issue
Block a user