diff --git a/include/libpmr/new.h b/include/libpmr/new.h new file mode 100644 index 00000000..61ac1f7d --- /dev/null +++ b/include/libpmr/new.h @@ -0,0 +1,86 @@ +/** + * \file libpmr/new.h + * \author mutouyun (orz@orzz.org) + * \brief Global object creation function. + * \date 2024-01-01 + */ +#pragma once + +#include + +#include "libimp/aligned.h" +#include "libimp/uninitialized.h" + +#include "libpmr/def.h" +#include "libpmr/block_pool.h" +#include "libpmr/memory_resource.h" + +LIBPMR_NAMESPACE_BEG_ + +constexpr inline std::size_t regular_level(std::size_t s) noexcept { + if (s <= 128 ) return 0; + if (s <= 1024 ) return 1; + if (s <= 8192 ) return 2; + if (s <= 65536) return 3; + return 4; +} + +constexpr inline std::size_t regular_sizeof(std::size_t s) noexcept { + switch (regular_level(s)) { + case 0 : return ::LIBIMP::round_up(s, 8); + case 1 : return ::LIBIMP::round_up(s, 128); + case 2 : return ::LIBIMP::round_up(s, 1024); + case 3 : return ::LIBIMP::round_up(s, 8192); + default: return 0; + } +} + +template +constexpr inline std::size_t regular_sizeof() noexcept { + return regular_sizeof(sizeof(T)); +} + +template +class block_pool_resource : public block_pool { +public: + static block_pool_resource *get() noexcept { + thread_local block_pool_resource instance; + return &instance; + } + void *allocate(std::size_t /*bytes*/, std::size_t /*alignment*/ = alignof(std::max_align_t)) noexcept { + return block_pool::allocate(); + } + void deallocate(void *p, std::size_t /*bytes*/, std::size_t /*alignment*/ = alignof(std::max_align_t)) noexcept { + block_pool::deallocate(p); + } +}; + +template +class regular_resource : public new_delete_resource {}; + +template +class regular_resource : public block_pool_resource {}; + +template +class regular_resource : public block_pool_resource {}; + +template +class regular_resource : public block_pool_resource {}; + +template +class regular_resource : public block_pool_resource {}; + +template +T *new_(A &&... args) noexcept { + auto *mem_res = regular_resource()>::get(); + return ::LIBIMP::construct(mem_res->allocate(sizeof(T), alignof(T)), std::forward(args)...); +} + +template +void delete_(T *p) noexcept { + if (p == nullptr) return; + auto *mem_res = regular_resource()>::get(); + mem_res->deallocate(::LIBIMP::destroy(p), sizeof(T), alignof(T)); +} + +LIBPMR_NAMESPACE_END_ diff --git a/src/libpmr/memory_resource.cpp b/src/libpmr/memory_resource.cpp index 7231154f..1ac95ebe 100644 --- a/src/libpmr/memory_resource.cpp +++ b/src/libpmr/memory_resource.cpp @@ -8,23 +8,9 @@ #include "libpmr/memory_resource.h" -LIBPMR_NAMESPACE_BEG_ -namespace { - -/** - * \brief Check that bytes is not 0 and that the alignment is a power of two. - */ -bool verify_args(std::size_t bytes, std::size_t alignment) noexcept { - if (bytes == 0) { - return false; - } - if ((alignment == 0) || (alignment & (alignment - 1)) != 0) { - return false; - } - return true; -} +#include "verify_args.h" -} // namespace +LIBPMR_NAMESPACE_BEG_ /** * \brief Returns a pointer to a new_delete_resource. diff --git a/src/libpmr/synchronized_pool_resource.cpp b/src/libpmr/synchronized_pool_resource.cpp index 0c44d886..f14c9966 100644 --- a/src/libpmr/synchronized_pool_resource.cpp +++ b/src/libpmr/synchronized_pool_resource.cpp @@ -2,10 +2,38 @@ #include "libimp/log.h" #include "libpmr/synchronized_pool_resource.h" +#include "libpmr/block_pool.h" + +#include "verify_args.h" LIBPMR_NAMESPACE_BEG_ namespace { } // namespace +synchronized_pool_resource *synchronized_pool_resource::get() noexcept { + static synchronized_pool_resource mem_res; + return &mem_res; +} + +void *synchronized_pool_resource::allocate(std::size_t bytes, std::size_t alignment) noexcept { + LIBIMP_LOG_(); + if (!verify_args(bytes, alignment) || (alignment > alignof(std::max_align_t))) { + log.error("invalid bytes = ", bytes, ", alignment = ", alignment); + return nullptr; + } + return nullptr; +} + +void synchronized_pool_resource::deallocate(void *p, std::size_t bytes, std::size_t alignment) noexcept { + LIBIMP_LOG_(); + if (p == nullptr) { + return; + } + if (!verify_args(bytes, alignment) || (alignment > alignof(std::max_align_t))) { + log.error("invalid bytes = ", bytes, ", alignment = ", alignment); + return; + } +} + LIBPMR_NAMESPACE_END_ diff --git a/src/libpmr/verify_args.h b/src/libpmr/verify_args.h new file mode 100644 index 00000000..fceaccf5 --- /dev/null +++ b/src/libpmr/verify_args.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +#include "libpmr/def.h" + +LIBPMR_NAMESPACE_BEG_ + +/** + * \brief Check that bytes is not 0 and that the alignment is a power of two. + */ +inline bool verify_args(std::size_t bytes, std::size_t alignment) noexcept { + if (bytes == 0) { + return false; + } + if ((alignment == 0) || (alignment & (alignment - 1)) != 0) { + return false; + } + return true; +} + +LIBPMR_NAMESPACE_END_ diff --git a/test/pmr/test_pmr_new.cpp b/test/pmr/test_pmr_new.cpp new file mode 100644 index 00000000..96d59e74 --- /dev/null +++ b/test/pmr/test_pmr_new.cpp @@ -0,0 +1,5 @@ + +#include "gtest/gtest.h" + +#include "libpmr/new.h" +