diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-03-24 23:49:26 +0100 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-03-24 23:49:26 +0100 |
commit | 00c0d78199fcfbbb20828be5e06fd2d271fa4c1e (patch) | |
tree | e74aa52990af33f7bf1e4d452b464c3e24d1017e /deimos/core |
Initial commit
Diffstat (limited to 'deimos/core')
-rw-r--r-- | deimos/core/BUILD | 14 | ||||
-rw-r--r-- | deimos/core/allocator.cpp | 55 | ||||
-rw-r--r-- | deimos/core/allocator.h | 74 | ||||
-rw-r--r-- | deimos/core/api_registry.cpp | 47 | ||||
-rw-r--r-- | deimos/core/api_registry.h | 30 | ||||
-rw-r--r-- | deimos/core/base.h | 87 | ||||
-rw-r--r-- | deimos/core/hash.h | 110 | ||||
-rw-r--r-- | deimos/core/id_name.h | 21 |
8 files changed, 438 insertions, 0 deletions
diff --git a/deimos/core/BUILD b/deimos/core/BUILD new file mode 100644 index 0000000..2093642 --- /dev/null +++ b/deimos/core/BUILD @@ -0,0 +1,14 @@ +cc_library(
+ name = "core",
+ hdrs = [
+ "base.h",
+ "allocator.h",
+ "api_registry.h",
+ ],
+ srcs = [
+ "allocator.cpp",
+ "api_registry.cpp",
+ ],
+ visibility = ["//:__subpackages__"],
+)
+
diff --git a/deimos/core/allocator.cpp b/deimos/core/allocator.cpp new file mode 100644 index 0000000..a525bfd --- /dev/null +++ b/deimos/core/allocator.cpp @@ -0,0 +1,55 @@ +#include "deimos/core/allocator.h"
+
+#include <cstdlib>
+
+namespace deimos
+{
+
+class SystemAllocatorImpl : public IAllocator
+{
+public:
+ SystemAllocatorImpl() : IAllocator(MemoryScope{0}) {}
+
+ void* Reallocate(
+ void* old_ptr, int64 /* old_size */, int64 new_size,
+ const char* /* file */, int32 /* line */) override
+ {
+ if (old_ptr == nullptr)
+ {
+ return new_size > 0 ? ::malloc((uint64)new_size) : nullptr;
+ }
+
+ if (new_size == 0)
+ {
+ if (old_ptr != nullptr)
+ {
+ ::free(old_ptr);
+ }
+ }
+ else
+ {
+ return ::realloc(old_ptr, (uint64)new_size);
+ }
+ return nullptr;
+ }
+};
+
+class AllocatorApiImpl : public AllocatorApi
+{
+ SystemAllocatorImpl m_system_impl;
+
+public:
+ AllocatorApiImpl()
+ {
+ system = &m_system_impl;
+ }
+};
+
+AllocatorApi* BootstrapAllocatorApi()
+{
+ static AllocatorApiImpl g_instance{};
+ return &g_instance;
+}
+
+} // namespace deimos
+
diff --git a/deimos/core/allocator.h b/deimos/core/allocator.h new file mode 100644 index 0000000..4acdb6d --- /dev/null +++ b/deimos/core/allocator.h @@ -0,0 +1,74 @@ +#pragma once
+
+#include "deimos/core/base.h"
+#include "deimos/core/id_name.h"
+
+namespace deimos
+{
+
+struct MemoryScope { uint32 id; };
+
+class IAllocator
+{
+protected:
+ const MemoryScope m_scope;
+
+public:
+ constexpr explicit IAllocator(MemoryScope scope) : m_scope{scope} {}
+
+ deimos_NO_COPY_MOVE(IAllocator);
+
+ virtual ~IAllocator() = default;
+
+ [[nodiscard]]
+ virtual void* Reallocate(
+ void* old_ptr, int64 old_size, int64 new_size,
+ const char* file = __builtin_FILE(), int32 line = __builtin_LINE()) = 0;
+
+ [[nodiscard]]
+ constexpr void* Allocate(
+ int64 new_size,
+ const char* file = __builtin_FILE(), int32 line = __builtin_LINE())
+ {
+ return Reallocate(nullptr, 0, new_size, file, line);
+ }
+
+ constexpr void Free(
+ void* old_ptr, int64 old_size,
+ const char* file = __builtin_FILE(), int32 line = __builtin_LINE())
+ {
+ (void)Reallocate(old_ptr, old_size, 0, file, line);
+ }
+
+ template<typename T, typename... Args>
+ T* New(
+ Args&&... args,
+ const char* file = __builtin_FILE(), int32 line = __builtin_LINE())
+ {
+ void* ptr = Allocate(sizeof(T), file, line);
+ return new(ptr) T(std::forward<Args>(args)...);
+ }
+
+ template<typename T>
+ void Delete(
+ T* t,
+ const char* file = __builtin_FILE(), int32 line = __builtin_LINE())
+ {
+ if constexpr (!kIsTriviallyDestructible<T>)
+ {
+ t->~T();
+ }
+ Free(t, sizeof(T), file, line);
+ }
+};
+
+class AllocatorApi
+{
+public:
+ static constexpr IdName kApiName{"deimos::AllocatorApi"};
+
+ IAllocator* system{};
+};
+
+} // namespace deimos
+
diff --git a/deimos/core/api_registry.cpp b/deimos/core/api_registry.cpp new file mode 100644 index 0000000..aa993e0 --- /dev/null +++ b/deimos/core/api_registry.cpp @@ -0,0 +1,47 @@ +#include "deimos/core/api_registry.h"
+#include "deimos/core/allocator.h"
+#include "deimos/core/hash.h"
+
+namespace deimos
+{
+
+AllocatorApi* BootstrapAllocatorApi();
+
+struct ApiEntry
+{
+ const ApiEntry* next{};
+ IdName name;
+ void* impl;
+
+ ApiEntry(const IdName& name, void* impl) :
+ name{name}, impl{impl}
+ {}
+};
+
+class ApiRegistryImpl: public ApiRegistry
+{
+ IAllocator* m_allocator;
+
+public:
+ explicit ApiRegistryImpl(IAllocator* allocator) :
+ m_allocator{allocator}
+ {}
+
+ void Set(const IdName& name, void* impl) final
+ {
+ }
+};
+
+ApiRegistry* InitializeGlobalApiRegistry()
+{
+ AllocatorApi* allocator_api = BootstrapAllocatorApi();
+ IAllocator* allocator = allocator_api->system;
+ ApiRegistry* api_registry = allocator->New<ApiRegistryImpl>();
+
+ api_registry->Set(allocator_api);
+
+ return api_registry;
+}
+
+} // namespace deimos
+
diff --git a/deimos/core/api_registry.h b/deimos/core/api_registry.h new file mode 100644 index 0000000..2624935 --- /dev/null +++ b/deimos/core/api_registry.h @@ -0,0 +1,30 @@ +#pragma once
+
+#include "deimos/core/base.h"
+#include "deimos/core/id_name.h"
+
+namespace deimos
+{
+
+class ApiRegistry
+{
+public:
+ ApiRegistry() = default;
+
+ deimos_NO_COPY_MOVE(ApiRegistry);
+
+ virtual ~ApiRegistry() = default;
+
+ virtual void Set(const IdName&, void* impl) = 0;
+
+ template<typename Api>
+ void Set(Api* impl)
+ {
+ Set(Api::kApiName, impl);
+ }
+};
+
+ApiRegistry* InitializeGlobalApiRegistry();
+
+} // namespace deimos
+
diff --git a/deimos/core/base.h b/deimos/core/base.h new file mode 100644 index 0000000..0530db7 --- /dev/null +++ b/deimos/core/base.h @@ -0,0 +1,87 @@ +#pragma once
+
+#define deimos_StaticAssert(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
+
+#define deimos_NO_COPY(TYPE) \
+ TYPE(const TYPE&) = delete; \
+ TYPE& operator=(const TYPE&) = delete;
+
+#define deimos_NO_MOVE(TYPE) \
+ TYPE(TYPE&&) = delete; \
+ TYPE& operator=(TYPE&&) = delete;
+
+#define deimos_NO_COPY_MOVE(TYPE) \
+ deimos_NO_COPY(TYPE); \
+ deimos_NO_MOVE(TYPE);
+
+#define deimos_DEFAULT_COPY(TYPE) \
+ TYPE(const TYPE&) = default; \
+ TYPE& operator=(const TYPE&) = default;
+
+#define deimos_DEFAULT_MOVE(TYPE) \
+ TYPE(TYPE&&) = default; \
+ TYPE& operator=(TYPE&&) = default;
+
+#define deimos_DEFAULT_COPY_MOVE(TYPE) \
+ deimos_DEFAULT_COPY(TYPE); \
+ deimos_DEFAULT_MOVE(TYPE);
+
+namespace deimos
+{
+
+using uint8 = unsigned char;
+using uint16 = unsigned short;
+using uint32 = unsigned int;
+using uint64 = unsigned long long;
+
+using int8 = char;
+using int16 = short;
+using int32 = int;
+using int64 = long long;
+
+using float32 = float;
+using float64 = double;
+
+struct uint128
+{
+ uint64 high;
+ uint64 low;
+};
+
+template<typename T> struct RemoveReferenceT { using Type = T; };
+template<typename T> struct RemoveReferenceT<T&> { using Type = T; };
+template<typename T> struct RemoveReferenceT<T&&> { using Type = T; };
+template<typename T> using RemoveReference = RemoveReferenceT<T>::Type;
+
+template<typename T> constexpr bool kIsTriviallyDestructible = __is_trivially_destructible(T);
+
+} // namespace deimos
+
+constexpr void* operator new(deimos::uint64, void* ptr)
+{
+ return ptr;
+}
+
+namespace std
+{
+
+template<typename T>
+constexpr deimos::RemoveReference<T>&& move(T&& t) noexcept
+{
+ return static_cast<deimos::RemoveReference<T>&&>(t);
+}
+
+template<typename T>
+constexpr T&& forward(deimos::RemoveReference<T>& t) noexcept
+{
+ return static_cast<T&&>(t);
+}
+
+template<typename T>
+constexpr T&& forward(deimos::RemoveReference<T>&& t) noexcept // NOLINT
+{
+ return static_cast<T&&>(t);
+}
+
+} // namespace std
+
diff --git a/deimos/core/hash.h b/deimos/core/hash.h new file mode 100644 index 0000000..3f8935c --- /dev/null +++ b/deimos/core/hash.h @@ -0,0 +1,110 @@ +#pragma once
+
+#include "deimos/core/base.h"
+
+namespace deimos
+{
+
+constexpr uint64 MurmurHash3_GetBlock64(const char* key, uint64 block)
+{
+ // NOLINTBEGIN
+ key += block * 8;
+ return
+ (uint64)((uint8)key[0])
+ | ((uint64)((uint8)key[1]) << 8)
+ | ((uint64)((uint8)key[2]) << 16)
+ | ((uint64)((uint8)key[3]) << 24)
+ | ((uint64)((uint8)key[4]) << 32)
+ | ((uint64)((uint8)key[5]) << 40)
+ | ((uint64)((uint8)key[6]) << 48)
+ | ((uint64)((uint8)key[7]) << 56);
+ // NOLINTEND
+}
+
+constexpr uint64 MurmurHash3_Fmix64(uint64 k)
+{
+ k ^= k >> 33U;
+ k *= 0xff51afd7ed558ccdULL;
+ k ^= k >> 33U;
+ k *= 0xc4ceb9fe1a85ec53ULL;
+ k ^= k >> 33U;
+ return k;
+}
+
+constexpr uint128 MurmurHash3_x64_128(const char* key)
+{
+ // NOLINTBEGIN
+ const uint64 len = __builtin_strlen(key);
+ const uint64 nblocks = len / 16;
+
+ const int64 seed = 0;
+ uint64 h1 = seed;
+ uint64 h2 = seed;
+
+ const uint64 c1 = 0x87c37b91114253d5ULL;
+ const uint64 c2 = 0x4cf5ad432745937fULL;
+
+ //----------
+ // body
+
+ for(uint64 i = 0; i < nblocks; i++)
+ {
+ uint64 k1 = MurmurHash3_GetBlock64(key, i * 2 + 0);
+ uint64 k2 = MurmurHash3_GetBlock64(key, i * 2 + 1);
+
+ k1 *= c1; k1 = _rotl64(k1, 31); k1 *= c2; h1 ^= k1;
+ h1 = _rotl64(h1, 27); h1 += h2; h1 = h1*5+0x52dce729;
+ k2 *= c2; k2 = _rotl64(k2, 33); k2 *= c1; h2 ^= k2;
+ h2 = _rotl64(h2, 31); h2 += h1; h2 = h2*5+0x38495ab5;
+ }
+
+ //----------
+ // tail
+
+ const char* tail = key + nblocks * 16;
+
+ uint64 k1 = 0;
+ uint64 k2 = 0;
+
+ switch (len & 15ULL)
+ {
+ case 15: k2 ^= ((uint64)(uint8)tail[14]) << 48U;
+ case 14: k2 ^= ((uint64)(uint8)tail[13]) << 40U;
+ case 13: k2 ^= ((uint64)(uint8)tail[12]) << 32U;
+ case 12: k2 ^= ((uint64)(uint8)tail[11]) << 24U;
+ case 11: k2 ^= ((uint64)(uint8)tail[10]) << 16U;
+ case 10: k2 ^= ((uint64)(uint8)tail[ 9]) << 8U;
+ case 9: k2 ^= ((uint64)(uint8)tail[ 8]) << 0U;
+ k2 *= c2; k2 = _rotl64(k2,33); k2 *= c1; h2 ^= k2;
+
+ case 8: k1 ^= ((uint64)(uint8)tail[ 7]) << 56U;
+ case 7: k1 ^= ((uint64)(uint8)tail[ 6]) << 48U;
+ case 6: k1 ^= ((uint64)(uint8)tail[ 5]) << 40U;
+ case 5: k1 ^= ((uint64)(uint8)tail[ 4]) << 32U;
+ case 4: k1 ^= ((uint64)(uint8)tail[ 3]) << 24U;
+ case 3: k1 ^= ((uint64)(uint8)tail[ 2]) << 16U;
+ case 2: k1 ^= ((uint64)(uint8)tail[ 1]) << 8U;
+ case 1: k1 ^= ((uint64)(uint8)tail[ 0]) << 0U;
+ k1 *= c1; k1 = _rotl64(k1,31); k1 *= c2; h1 ^= k1;
+ };
+
+ //----------
+ // finalization
+
+ h1 ^= len; h2 ^= len;
+
+ h1 += h2;
+ h2 += h1;
+
+ h1 = MurmurHash3_Fmix64(h1);
+ h2 = MurmurHash3_Fmix64(h2);
+
+ h1 += h2;
+ h2 += h1;
+ // NOLINTEND
+
+ return uint128{h1, h2};
+}
+
+} // namespace deimos
+
diff --git a/deimos/core/id_name.h b/deimos/core/id_name.h new file mode 100644 index 0000000..eb961ca --- /dev/null +++ b/deimos/core/id_name.h @@ -0,0 +1,21 @@ +#pragma once
+
+#include "deimos/core/base.h"
+#include "deimos/core/hash.h"
+
+namespace deimos
+{
+
+struct IdName
+{
+ uint128 hash;
+ const char* name;
+
+ explicit constexpr IdName(const char* name) :
+ hash{MurmurHash3_x64_128(name)},
+ name{name}
+ {}
+};
+
+} // namespace deimos
+
|