diff options
-rw-r--r-- | deimos/core/BUILD | 4 | ||||
-rw-r--r-- | deimos/core/allocator.h | 2 | ||||
-rw-r--r-- | deimos/core/api_registry.cpp | 2 | ||||
-rw-r--r-- | deimos/core/atomic.h | 2 | ||||
-rw-r--r-- | deimos/core/base.h | 17 | ||||
-rw-r--r-- | deimos/core/gsl.h | 4 | ||||
-rw-r--r-- | deimos/core/os.h | 4 | ||||
-rw-r--r-- | deimos/core/temp_allocator.cpp | 109 | ||||
-rw-r--r-- | deimos/core/temp_allocator.h | 65 | ||||
-rw-r--r-- | main/main.cpp | 1 | ||||
-rw-r--r-- | run_clang_tidy.py | 5 |
11 files changed, 206 insertions, 9 deletions
diff --git a/deimos/core/BUILD b/deimos/core/BUILD index 84ed375..f81101b 100644 --- a/deimos/core/BUILD +++ b/deimos/core/BUILD @@ -5,6 +5,7 @@ cc_library( "api_registry.h",
"atomic.h",
"base.h",
+ "format.h",
"gsl.h",
"hash.h",
"id_name.h",
@@ -13,7 +14,7 @@ cc_library( "os.h",
"status.h",
"std.h",
- "format.h",
+ "temp_allocator.h",
],
srcs = [
"allocator.cpp",
@@ -23,6 +24,7 @@ cc_library( "log.cpp",
"os_win32.cpp",
"status.cpp",
+ "temp_allocator.cpp",
],
visibility = ["//:__subpackages__"],
)
diff --git a/deimos/core/allocator.h b/deimos/core/allocator.h index e65f316..26374bd 100644 --- a/deimos/core/allocator.h +++ b/deimos/core/allocator.h @@ -29,7 +29,7 @@ class Allocator const MemoryScope m_scope;
public:
- constexpr explicit Allocator(IAllocator* allocator, MemoryScope scope) :
+ constexpr Allocator(IAllocator* allocator, MemoryScope scope) :
m_allocator{allocator}, m_scope{scope}
{}
diff --git a/deimos/core/api_registry.cpp b/deimos/core/api_registry.cpp index 41c0257..9d0c93f 100644 --- a/deimos/core/api_registry.cpp +++ b/deimos/core/api_registry.cpp @@ -8,6 +8,7 @@ namespace deimos AllocatorApi* BootstrapAllocatorApi();
void RegisterOsApi(ApiRegistry*);
+void RegisterTempAllocatorApi(ApiRegistry*);
void RegisterLogApi(ApiRegistry*);
void InitializeStatus(ApiRegistry*);
@@ -59,6 +60,7 @@ ApiRegistry* InitializeGlobalApiRegistry() InitializeStatus(api_registry);
RegisterOsApi(api_registry);
+ RegisterTempAllocatorApi(api_registry);
RegisterLogApi(api_registry);
return api_registry;
diff --git a/deimos/core/atomic.h b/deimos/core/atomic.h index c3d7947..e4f8569 100644 --- a/deimos/core/atomic.h +++ b/deimos/core/atomic.h @@ -5,7 +5,7 @@ namespace deimos
{
-enum class MemoryOrder : int
+enum class MemoryOrder : int // NOLINT(*-enum-size)
{
kRelaxed = __ATOMIC_RELAXED,
kAcquire = __ATOMIC_ACQUIRE,
diff --git a/deimos/core/base.h b/deimos/core/base.h index 1e9b4a9..f24991d 100644 --- a/deimos/core/base.h +++ b/deimos/core/base.h @@ -5,6 +5,8 @@ #define deimos_StaticAssert(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
+#define deimos_Panic(MSG) do { __builtin_trap(); } while (0)
+
#define deimos_NO_COPY(TYPE) \
TYPE(const TYPE&) = delete; \
TYPE& operator=(const TYPE&) = delete;
@@ -56,6 +58,21 @@ struct SourceLocation template<typename T> T Min(T a, T b) { return (a < b) ? a : b; }
template<typename T> T Max(T a, T b) { return (a > b) ? a : b; }
+[[maybe_unused]] static constexpr int64_t Kilobytes = 1024;
+[[maybe_unused]] static constexpr int64_t Megabytes = 1024 * 1024;
+[[maybe_unused]] static constexpr int64_t Gigabytes = 1024 * 1024 * 1024;
+
+constexpr int64_t AlignUp(int64_t value, int64_t align)
+{
+ return __builtin_align_up(value, align);
+}
+
+template<typename T>
+constexpr T* OffsetBytes(T* p, int64_t offset)
+{
+ return std::bit_cast<T*>(std::bit_cast<uintptr_t>(p) + std::bit_cast<uintptr_t>(offset));
+}
+
constexpr void MemoryCopy(void* dst, const void* src, int64_t size)
{
__builtin_memcpy(dst, src, (size_t)size);
diff --git a/deimos/core/gsl.h b/deimos/core/gsl.h index b54fc65..d80d746 100644 --- a/deimos/core/gsl.h +++ b/deimos/core/gsl.h @@ -10,5 +10,5 @@ template<typename T> using owner = T; } // namespace gsl
-#define Expects(EXPR) do { if (!(EXPR)) { __builtin_trap(); } } while (0)
-#define Ensures(EXPR) do { if (!(EXPR)) { __builtin_trap(); } } while (0)
+#define Expects(EXPR) do { if (EXPR) {} else { __builtin_trap(); } } while (0)
+#define Ensures(EXPR) do { if (EXPR) {} else { __builtin_trap(); } } while (0)
diff --git a/deimos/core/os.h b/deimos/core/os.h index 9aea509..271ecfb 100644 --- a/deimos/core/os.h +++ b/deimos/core/os.h @@ -61,8 +61,8 @@ public: class OsConsoleWriter : public IWriter
{
- OsConsoleApi* m_api;
- OsConsoleType m_type;
+ OsConsoleApi* m_api;
+ OsConsoleType m_type;
public:
constexpr OsConsoleWriter(OsConsoleApi* api, OsConsoleType type) :
diff --git a/deimos/core/temp_allocator.cpp b/deimos/core/temp_allocator.cpp new file mode 100644 index 0000000..2f07bcc --- /dev/null +++ b/deimos/core/temp_allocator.cpp @@ -0,0 +1,109 @@ +#include "deimos/core/temp_allocator.h"
+
+#include "deimos/core/api_registry.h"
+#include "deimos/core/allocator.h"
+#include "deimos/core/os.h"
+
+static deimos::OsApi* os_api;
+
+namespace deimos
+{
+
+class TempAllocatorImpl : public ITempAllocator
+{
+ static constexpr int64_t kDefaultAlign = 8;
+ static constexpr int64_t kPageSize = 1 * Megabytes;
+ static constexpr int64_t kReserveSize = 256 * Megabytes;
+
+ gsl::owner<void*> m_base{};
+ void* m_commit_end{};
+ void* m_reserve_end{};
+
+ // @Todo Last allocation optimization
+ void* m_current{};
+
+public:
+ gsl::owner<void*> Reallocate(TempAllocatorTag tag,
+ gsl::owner<void*> old_ptr, int64_t old_size, int64_t new_size) override
+ {
+ void* tag_ptr = std::bit_cast<void*>(tag.tag);
+ Expects(tag_ptr >= m_base && tag_ptr <= m_commit_end && tag_ptr <= m_current);
+
+ if (new_size <= old_size) { return (new_size == 0) ? nullptr : old_ptr; }
+
+ void* new_current = OffsetBytes(m_current, AlignUp(new_size, kDefaultAlign));
+ if (new_current > m_reserve_end)
+ {
+ deimos_Panic("Ran out of temporary memory");
+ return nullptr;
+ }
+
+ if (new_current > m_commit_end)
+ {
+ const int64_t new_commit_size = AlignUp(
+ (uint64_t)(std::bit_cast<uintptr_t>(new_current) - std::bit_cast<uintptr_t>(m_base)), // NOLINT
+ kPageSize);
+ os_api->virtual_memory->Commit(m_base, new_commit_size);
+ m_commit_end = OffsetBytes(m_base, new_commit_size);
+ Ensures(m_commit_end <= m_reserve_end);
+ }
+
+ if (old_ptr != nullptr)
+ {
+ MemoryCopy(m_current, old_ptr, old_size);
+ }
+
+ return std::exchange(m_current, new_current);
+ }
+
+ TempAllocator Acquire()
+ {
+ if (m_base == nullptr)
+ {
+ m_base = os_api->virtual_memory->Reserve(kReserveSize);
+ m_current = m_base;
+ m_commit_end = m_base;
+ m_reserve_end = OffsetBytes(m_base, kReserveSize);
+ }
+
+ return TempAllocator(this, {std::bit_cast<uintptr_t>(m_current)});
+ }
+
+ void Release(TempAllocatorTag tag) override
+ {
+ void* rewind_base = std::bit_cast<void*>(tag.tag);
+ Expects(rewind_base >= m_base && rewind_base <= m_commit_end);
+
+ if (rewind_base < m_current)
+ {
+ m_current = rewind_base;
+ }
+ else
+ {
+ deimos_Panic("Invalid temporary allocator rewind");
+ }
+ }
+};
+
+static thread_local TempAllocatorImpl g_impl;
+
+class TempAllocatorApiImpl : public TempAllocatorApi
+{
+public:
+ TempAllocator Acquire() override
+ {
+ return g_impl.Acquire();
+ }
+};
+
+void RegisterTempAllocatorApi(ApiRegistry* api_registry)
+{
+ os_api = api_registry->Get<OsApi>();
+
+ auto* allocator = api_registry->Get<AllocatorApi>()->system;
+ gsl::owner<TempAllocatorApi*> temp_allocator_api = allocator->New<TempAllocatorApiImpl>();
+ api_registry->Set(temp_allocator_api);
+}
+
+} // namespace deimos
+
diff --git a/deimos/core/temp_allocator.h b/deimos/core/temp_allocator.h index 4f80192..6d93a77 100644 --- a/deimos/core/temp_allocator.h +++ b/deimos/core/temp_allocator.h @@ -2,9 +2,74 @@ #include "deimos/core/base.h"
#include "deimos/core/id_name.h"
+#include "deimos/core/allocator.h"
namespace deimos
{
+struct TempAllocatorTag { uintptr_t tag; };
+
+class TempAllocatorApi;
+
+class ITempAllocator
+{
+public:
+ ITempAllocator() = default;
+ deimos_NO_COPY_MOVE(ITempAllocator);
+ virtual ~ITempAllocator() = default;
+
+ virtual gsl::owner<void*> Reallocate(TempAllocatorTag tag,
+ gsl::owner<void*> old_ptr, int64_t old_size, int64_t new_size) = 0;
+
+ virtual void Release(TempAllocatorTag tag) = 0;
+};
+
+class TempAllocator : public IAllocator
+{
+ ITempAllocator* m_inner;
+ TempAllocatorTag m_tag;
+
+public:
+ TempAllocator(ITempAllocator* inner, TempAllocatorTag tag) :
+ m_inner{inner}, m_tag{tag}
+ {}
+
+ deimos_NO_COPY_MOVE(TempAllocator);
+
+ ~TempAllocator() override;
+
+ [[nodiscard]]
+ gsl::owner<void*> Reallocate(
+ gsl::owner<void*> old_ptr, int64_t old_size, int64_t new_size,
+ MemoryScope scope, const SourceLocation& source_location = {}) override;
+
+ constexpr Allocator allocator() { return Allocator(this, MemoryScope{0}); }
+};
+
+class TempAllocatorApi
+{
+public:
+ TempAllocatorApi() = default;
+ deimos_NO_COPY_MOVE(TempAllocatorApi);
+ virtual ~TempAllocatorApi() = default;
+
+ static constexpr IdName kApiName{"deimos::TempAllocatorApi"};
+
+ [[nodiscard]] virtual TempAllocator Acquire() = 0;
+};
+
+[[nodiscard]]
+inline gsl::owner<void*> TempAllocator::Reallocate(
+ gsl::owner<void*> old_ptr, int64_t old_size, int64_t new_size,
+ MemoryScope, const SourceLocation&)
+{
+ return m_inner->Reallocate(m_tag, old_ptr, old_size, new_size);
+}
+
+inline TempAllocator::~TempAllocator()
+{
+ m_inner->Release(m_tag);
+}
+
} // namespace deimos
diff --git a/main/main.cpp b/main/main.cpp index 4d1834d..7a46861 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1,6 +1,7 @@ #include <deimos/core/api_registry.h>
#include <deimos/core/log.h>
#include <deimos/core/os.h>
+#include <deimos/core/temp_allocator.h>
using namespace deimos;
diff --git a/run_clang_tidy.py b/run_clang_tidy.py index 40d4a5e..76ef959 100644 --- a/run_clang_tidy.py +++ b/run_clang_tidy.py @@ -9,9 +9,10 @@ def has_extension(extensions): return path.suffix in extensions
return f
-ROOTS = ["./deimos", "./game"]
+ROOTS = ["./deimos", "./main"]
for root in ROOTS:
for file in filter(has_extension([".cpp", ".c"]), filter(is_file, pathlib.Path(root).rglob("*"))):
- subprocess.run(["clang-tidy", file, "-header-filter=deimos|game"])
+ print(file)
+ subprocess.run(["clang-tidy", file, "-header-filter=deimos|main"])
|