#pragma once #include #include #include #include inline void* operator new(size_t, void* ptr) { return ptr; } namespace types { template concept Allocator = requires(size_t size, typename T::value_type* ptr) { typename T::value_type; { T::allocate_memory(size) } -> same_as; { T::deallocate_memory(ptr) } -> same_as; }; template class allocator_traits; template class kernel_allocator { public: using value_type = T; static value_type* allocate_memory(size_t count) { return static_cast(::k_malloc(count)); } static void deallocate_memory(value_type* ptr) { ::k_free(ptr); } }; template class kernel_ident_allocator { public: using value_type = T; static value_type* allocate_memory(size_t count) { return static_cast(::ki_malloc(count)); } static void deallocate_memory(value_type* ptr) { ::ki_free(ptr); } }; template constexpr T* kernel_allocator_new(Args&&... args) { return allocator_traits>::allocate_and_construct(forward(args)...); } template constexpr T* kernel_ident_allocator_new(Args&&... args) { return allocator_traits>::allocate_and_construct(forward(args)...); } template class allocator_traits { public: using value_type = typename _allocator::value_type; static value_type* allocate(size_t count) { if (count == 0) return nullptr; return _allocator::allocate_memory(sizeof(value_type) * count); } template static value_type* construct(value_type* ptr, Args&&... args) { new (ptr) value_type(forward(args)...); return ptr; } template static value_type* allocate_and_construct(Args&&... args) { auto* ptr = allocate(1); construct(ptr, forward(args)...); return ptr; } static void deconstruct(value_type* ptr) { if (!ptr) return; ptr->~value_type(); } static void deallocate(value_type* ptr) { if (!ptr) return; _allocator::deallocate_memory(ptr); } static void deconstruct_and_deallocate(value_type* ptr) { if (!ptr) return; deconstruct(ptr); deallocate(ptr); } }; } // namespace types