summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-tidy2
-rw-r--r--deimos/core/BUILD2
-rw-r--r--deimos/core/allocator.cpp4
-rw-r--r--deimos/core/allocator.h8
-rw-r--r--deimos/core/api_registry.cpp2
-rw-r--r--deimos/core/base.h27
-rw-r--r--deimos/core/status.cpp70
-rw-r--r--deimos/core/status.h111
-rw-r--r--deimos/core/std.h2
-rw-r--r--deimos/core/temp_allocator.h10
10 files changed, 232 insertions, 6 deletions
diff --git a/.clang-tidy b/.clang-tidy
index 84322ba..bdee056 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -21,3 +21,5 @@ Checks:
- "-*-avoid-c-arrays"
- "-*-use-anonymous-namespace"
- "-*-reinterpret-cast"
+ - "-*-noexcept-move"
+ - "-*-noexcept-move-constructor"
diff --git a/deimos/core/BUILD b/deimos/core/BUILD
index 08f1ada..e4bfee8 100644
--- a/deimos/core/BUILD
+++ b/deimos/core/BUILD
@@ -10,6 +10,7 @@ cc_library(
"io.h",
"log.h",
"os.h",
+ "status.h",
"std.h",
"format.h",
],
@@ -20,6 +21,7 @@ cc_library(
"io.cpp",
"log.cpp",
"os_win32.cpp",
+ "status.cpp",
],
visibility = ["//:__subpackages__"],
)
diff --git a/deimos/core/allocator.cpp b/deimos/core/allocator.cpp
index b42861c..cd3de9e 100644
--- a/deimos/core/allocator.cpp
+++ b/deimos/core/allocator.cpp
@@ -8,8 +8,8 @@ namespace deimos
class SystemAllocatorImpl : public IAllocator
{
public:
- gsl::owner<void*> Reallocate(
- gsl::owner<void*> old_ptr, int64_t /* old_size */, int64_t new_size,
+ void* Reallocate(
+ void* old_ptr, int64_t /* old_size */, int64_t new_size,
MemoryScope /* scope */, const SourceLocation& /* source_location */) override
{
if (old_ptr == nullptr)
diff --git a/deimos/core/allocator.h b/deimos/core/allocator.h
index e65f316..8f00610 100644
--- a/deimos/core/allocator.h
+++ b/deimos/core/allocator.h
@@ -40,7 +40,7 @@ public:
constexpr IAllocator* allocator() const { return m_allocator; }
[[nodiscard]]
- constexpr gsl::owner<void*> Allocate(
+ constexpr void* Allocate(
int64_t new_size,
const SourceLocation& source_location = {})
{
@@ -48,15 +48,15 @@ public:
}
[[nodiscard]]
- gsl::owner<void*> Reallocate(
- gsl::owner<void*> old_ptr, int64_t old_size, int64_t new_size,
+ void* Reallocate(
+ void* old_ptr, int64_t old_size, int64_t new_size,
const SourceLocation& source_location = {})
{
return m_allocator->Reallocate(old_ptr, old_size, new_size, m_scope, source_location);
}
constexpr void Free(
- gsl::owner<void*> old_ptr, int64_t old_size,
+ void* old_ptr, int64_t old_size,
const SourceLocation& source_location = {})
{
(void)m_allocator->Reallocate(old_ptr, old_size, 0, m_scope, source_location);
diff --git a/deimos/core/api_registry.cpp b/deimos/core/api_registry.cpp
index 81dabf0..41c0257 100644
--- a/deimos/core/api_registry.cpp
+++ b/deimos/core/api_registry.cpp
@@ -9,6 +9,7 @@ namespace deimos
AllocatorApi* BootstrapAllocatorApi();
void RegisterOsApi(ApiRegistry*);
void RegisterLogApi(ApiRegistry*);
+void InitializeStatus(ApiRegistry*);
struct ApiEntry
{
@@ -56,6 +57,7 @@ ApiRegistry* InitializeGlobalApiRegistry()
api_registry->Set(g_allocator_api);
+ InitializeStatus(api_registry);
RegisterOsApi(api_registry);
RegisterLogApi(api_registry);
diff --git a/deimos/core/base.h b/deimos/core/base.h
index 64d1ed9..1022ae8 100644
--- a/deimos/core/base.h
+++ b/deimos/core/base.h
@@ -104,5 +104,32 @@ inline Span<const std::byte> AsBytes(Span<T> span)
return { reinterpret_cast<const std::byte*>(span.data()), span.size() * (int64_t)sizeof(T) };
}
+class StringView
+{
+ const char* m_begin = nullptr;
+ int64_t m_size = 0;
+
+public:
+ constexpr StringView() = default;
+
+ deimos_DEFAULT_COPY_MOVE(StringView);
+ ~StringView() = default;
+
+ constexpr StringView(gsl::czstring str) : // NOLINT(*-explicit-conversions)
+ m_begin{str}, m_size{(int64_t)__builtin_strlen(str)}
+ {}
+
+ constexpr StringView(const char* begin, int64_t size) :
+ m_begin{begin}, m_size{size}
+ {}
+
+ constexpr const char* data() const { return m_begin; }
+
+ constexpr int64_t size() const { return m_size; }
+};
+
+deimos_StaticAssert(std::is_trivially_destructible_v<StringView>);
+deimos_StaticAssert(std::is_trivially_copyable_v<StringView>);
+
} // namespace deimos
diff --git a/deimos/core/status.cpp b/deimos/core/status.cpp
new file mode 100644
index 0000000..ed1a665
--- /dev/null
+++ b/deimos/core/status.cpp
@@ -0,0 +1,70 @@
+#include "deimos/core/status.h"
+
+#include "deimos/core/api_registry.h"
+#include "deimos/core/allocator.h"
+
+static deimos::AllocatorApi* allocator_api;
+
+namespace deimos
+{
+
+Status::Status(StatusCode code, StringView message)
+{
+ if (code == StatusCode::kOk)
+ {
+ m_rep = CodeToRep(StatusCode::kOk);
+ }
+ else
+ {
+ void* ptr = allocator_api->system->Allocate((int64_t)sizeof(StatusRep) + message.size() + 1);
+ auto* rep = new(ptr) StatusRep;
+
+ char* message_ptr = (char*)ptr + sizeof(StatusRep); // NOLINT
+ MemoryCopy(message_ptr, message.data(), message.size());
+ message_ptr[message.size()] = '\0'; // NOLINT
+
+ rep->ref_count = 1;
+ rep->code = code;
+ rep->message = StringView(message_ptr, message.size());
+
+ m_rep = std::bit_cast<uintptr_t>(rep);
+ Ensures((m_rep & 1U) == 0);
+ }
+}
+
+void Status::Ref() const
+{
+ if (!IsInline())
+ {
+ auto* rep = std::bit_cast<StatusRep*>(m_rep);
+
+ Expects(rep->ref_count > 0);
+ rep->ref_count += 1;
+ }
+}
+
+void Status::Unref() const
+{
+ if (!IsInline())
+ {
+ auto* rep = std::bit_cast<StatusRep*>(m_rep);
+
+ Expects(rep->ref_count > 0);
+ rep->ref_count -= 1;
+
+ if (rep->ref_count == 0)
+ {
+ deimos_StaticAssert(std::is_trivially_destructible_v<StatusRep>);
+ allocator_api->system->Free(
+ rep, (int64_t)sizeof(StatusRep) + rep->message.size() + 1);
+ }
+ }
+}
+
+void InitializeStatus(ApiRegistry* api_registry)
+{
+ allocator_api = api_registry->Get<AllocatorApi>();
+}
+
+} // namespace deimos
+
diff --git a/deimos/core/status.h b/deimos/core/status.h
new file mode 100644
index 0000000..f866182
--- /dev/null
+++ b/deimos/core/status.h
@@ -0,0 +1,111 @@
+#pragma once
+
+#include "deimos/core/base.h"
+
+namespace deimos
+{
+
+enum class StatusCode : uint32_t
+{
+ kOk = 0,
+ kUnknown,
+ kInvalidArgument,
+ kUnimplemented,
+ kInternal,
+};
+
+struct StatusRep
+{
+ // @Todo Make this atomic
+ int32_t ref_count{};
+ StatusCode code{};
+ StringView message;
+};
+
+class Status
+{
+ uintptr_t m_rep;
+
+ constexpr bool IsInline() const
+ {
+ return (m_rep & 1U) == 1U;
+ }
+
+ static constexpr uintptr_t CodeToRep(StatusCode code)
+ {
+ return ((uint32_t)code << 1U) | 1U;
+ }
+
+ void Ref() const;
+ void Unref() const;
+
+public:
+ constexpr Status() : Status(StatusCode::kOk) {}
+ constexpr explicit Status(StatusCode code) : m_rep{CodeToRep(code)} {}
+ Status(StatusCode code, StringView message);
+
+ Status(const Status& other) : m_rep{other.m_rep}
+ {
+ Ref();
+ }
+
+ Status(Status&& other) : m_rep{std::exchange(other.m_rep, 0U)} {}
+
+ Status& operator=(const Status& other)
+ {
+ if (this != &other)
+ {
+ Unref();
+ this->m_rep = other.m_rep;
+ Ref();
+ }
+ return *this;
+ }
+
+ Status& operator=(Status&& other)
+ {
+ if (this != &other)
+ {
+ Unref();
+ this->m_rep = std::exchange(other.m_rep, 0U);
+
+ }
+ return *this;
+ }
+
+ ~Status()
+ {
+ Unref();
+ }
+
+ constexpr bool ok() const { return m_rep == CodeToRep(StatusCode::kOk); }
+
+ StatusCode code() const
+ {
+ if (IsInline()) { return (StatusCode)(m_rep >> 1U); }
+ return std::bit_cast<StatusRep*>(m_rep)->code;
+ }
+};
+
+inline Status UnknownError(StringView message = {})
+{
+ return Status(StatusCode::kUnknown, message);
+}
+
+inline Status InvalidArgumentError(StringView message = {})
+{
+ return Status(StatusCode::kInvalidArgument, message);
+}
+
+inline Status UnimplementedError(StringView message = {})
+{
+ return Status(StatusCode::kUnimplemented, message);
+}
+
+inline Status InternalError(StringView message = {})
+{
+ return Status(StatusCode::kInternal, message);
+}
+
+} // namespace deimos
+
diff --git a/deimos/core/std.h b/deimos/core/std.h
index 42bedbe..4bb2983 100644
--- a/deimos/core/std.h
+++ b/deimos/core/std.h
@@ -11,8 +11,10 @@ using int32_t = signed int;
using int64_t = signed long long;
using size_t = uint64_t;
+using uintptr_t = uint64_t;
static_assert(sizeof(size_t) == sizeof(void*), "size_t should be pointer size");
+static_assert(sizeof(uintptr_t) == sizeof(void*), "size_t should be pointer size");
namespace std
{
diff --git a/deimos/core/temp_allocator.h b/deimos/core/temp_allocator.h
new file mode 100644
index 0000000..4f80192
--- /dev/null
+++ b/deimos/core/temp_allocator.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "deimos/core/base.h"
+#include "deimos/core/id_name.h"
+
+namespace deimos
+{
+
+} // namespace deimos
+