From 10c0d14de6ade5535a9c67bb2c5312f131c0867c Mon Sep 17 00:00:00 2001 From: mutouyun Date: Thu, 13 Feb 2025 15:28:14 +0800 Subject: [PATCH] Reimplement the allocator required for the container type with `$new` --- ...ymorphic_allocator.h => bytes_allocator.h} | 89 +---------------- include/libipc/mem/central_cache_allocator.h | 2 +- include/libipc/mem/container_allocator.h | 95 +++++++++++++++++++ include/libipc/mem/memory_resource.h | 2 +- ...phic_allocator.cpp => bytes_allocator.cpp} | 2 +- src/libipc/mem/central_cache_allocator.cpp | 2 +- src/libipc/mem/resource.h | 6 +- ...cator.cpp => test_mem_bytes_allocator.cpp} | 20 ++-- 8 files changed, 115 insertions(+), 103 deletions(-) rename include/libipc/mem/{polymorphic_allocator.h => bytes_allocator.h} (64%) create mode 100644 include/libipc/mem/container_allocator.h rename src/libipc/mem/{polymorphic_allocator.cpp => bytes_allocator.cpp} (96%) rename test/mem/{test_mem_allocator.cpp => test_mem_bytes_allocator.cpp} (83%) diff --git a/include/libipc/mem/polymorphic_allocator.h b/include/libipc/mem/bytes_allocator.h similarity index 64% rename from include/libipc/mem/polymorphic_allocator.h rename to include/libipc/mem/bytes_allocator.h index 9c7f691..c9c6322 100644 --- a/include/libipc/mem/polymorphic_allocator.h +++ b/include/libipc/mem/bytes_allocator.h @@ -1,5 +1,5 @@ /** - * \file libipc/polymorphic_allocator + * \file libipc/bytes_allocator.h * \author mutouyun (orz@orzz.org) * \brief A generic polymorphic memory allocator. */ @@ -50,13 +50,13 @@ using is_memory_resource = * \brief An allocator which exhibits different allocation behavior * depending upon the memory resource from which it is constructed. * - * \note Unlike `std::pmr::polymorphic_allocator`, it does not + * \note Unlike `std::pmr::container_allocator`, it does not * rely on a specific inheritance relationship and only restricts * the interface behavior of the incoming memory resource object to * conform to `std::pmr::memory_resource`. * * \see https://en.cppreference.com/w/cpp/memory/memory_resource - * https://en.cppreference.com/w/cpp/memory/polymorphic_allocator + * https://en.cppreference.com/w/cpp/memory/container_allocator */ class LIBIPC_EXPORT bytes_allocator { @@ -159,88 +159,5 @@ public: } }; -/** - * \brief An allocator that can be used by all standard library containers, - * based on ipc::bytes_allocator. - * - * \see https://en.cppreference.com/w/cpp/memory/allocator - * https://en.cppreference.com/w/cpp/memory/polymorphic_allocator - */ -template -class polymorphic_allocator { - - template - friend class polymorphic_allocator; - -public: - // type definitions - typedef T value_type; - typedef value_type * pointer; - typedef const value_type *const_pointer; - typedef value_type & reference; - typedef const value_type &const_reference; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - -private: - bytes_allocator alloc_; - -public: - // the other type of std_allocator - template - struct rebind { - using other = polymorphic_allocator; - }; - - polymorphic_allocator() noexcept {} - - template = true> - polymorphic_allocator(P *p_mr) noexcept : alloc_(p_mr) {} - - // construct by copying (do nothing) - polymorphic_allocator (polymorphic_allocator const &) noexcept {} - polymorphic_allocator& operator=(polymorphic_allocator const &) noexcept { return *this; } - - // construct from a related allocator (do nothing) - template polymorphic_allocator (polymorphic_allocator const &) noexcept {} - template polymorphic_allocator &operator=(polymorphic_allocator const &) noexcept { return *this; } - - polymorphic_allocator (polymorphic_allocator &&) noexcept = default; - polymorphic_allocator& operator=(polymorphic_allocator &&) noexcept = default; - - constexpr size_type max_size(void) const noexcept { - return (std::numeric_limits::max)() / sizeof(value_type); - } - - pointer allocate(size_type count) noexcept { - if (count == 0) return nullptr; - if (count > this->max_size()) return nullptr; - return static_cast(alloc_.allocate(count * sizeof(value_type), alignof(T))); - } - - void deallocate(pointer p, size_type count) noexcept { - alloc_.deallocate(p, count * sizeof(value_type), alignof(T)); - } - - template - static void construct(pointer p, P && ... params) { - std::ignore = ipc::construct(p, std::forward

(params)...); - } - - static void destroy(pointer p) { - std::ignore = ipc::destroy(p); - } -}; - -template -constexpr bool operator==(polymorphic_allocator const &, polymorphic_allocator const &) noexcept { - return true; -} - -template -constexpr bool operator!=(polymorphic_allocator const &, polymorphic_allocator const &) noexcept { - return false; -} - } // namespace mem } // namespace ipc diff --git a/include/libipc/mem/central_cache_allocator.h b/include/libipc/mem/central_cache_allocator.h index d4770b6..02992a0 100644 --- a/include/libipc/mem/central_cache_allocator.h +++ b/include/libipc/mem/central_cache_allocator.h @@ -6,7 +6,7 @@ #pragma once #include "libipc/imp/export.h" -#include "libipc/mem/polymorphic_allocator.h" +#include "libipc/mem/bytes_allocator.h" namespace ipc { namespace mem { diff --git a/include/libipc/mem/container_allocator.h b/include/libipc/mem/container_allocator.h new file mode 100644 index 0000000..a01adac --- /dev/null +++ b/include/libipc/mem/container_allocator.h @@ -0,0 +1,95 @@ +/** + * \file libipc/container_allocator.h + * \author mutouyun (orz@orzz.org) + * \brief An allocator that can be used by all standard library containers. + */ +#pragma once + +#include +#include + +#include "libipc/imp/uninitialized.h" +#include "libipc/mem/new.h" + +namespace ipc { +namespace mem { + +/** + * \brief An allocator that can be used by all standard library containers. + * + * \see https://en.cppreference.com/w/cpp/memory/allocator + * https://en.cppreference.com/w/cpp/memory/polymorphic_allocator + */ +template +class container_allocator { + + template + friend class container_allocator; + +public: + // type definitions + typedef T value_type; + typedef value_type * pointer; + typedef const value_type *const_pointer; + typedef value_type & reference; + typedef const value_type &const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + // the other type of std_allocator + template + struct rebind { + using other = container_allocator; + }; + + container_allocator() noexcept {} + + // construct by copying (do nothing) + container_allocator (container_allocator const &) noexcept {} + container_allocator& operator=(container_allocator const &) noexcept { return *this; } + + // construct from a related allocator (do nothing) + template container_allocator (container_allocator const &) noexcept {} + template container_allocator &operator=(container_allocator const &) noexcept { return *this; } + + container_allocator (container_allocator &&) noexcept = default; + container_allocator& operator=(container_allocator &&) noexcept = default; + + constexpr size_type max_size() const noexcept { + return 1; + } + + pointer allocate(size_type count) noexcept { + if (count == 0) return nullptr; + if (count > this->max_size()) return nullptr; + return mem::$new(); + } + + void deallocate(pointer p, size_type count) noexcept { + if (count == 0) return; + if (count > this->max_size()) return; + mem::$delete(p); + } + + template + static void construct(pointer p, P && ... params) { + std::ignore = ipc::construct(p, std::forward

(params)...); + } + + static void destroy(pointer p) { + std::ignore = ipc::destroy(p); + } +}; + +template +constexpr bool operator==(container_allocator const &, container_allocator const &) noexcept { + return true; +} + +template +constexpr bool operator!=(container_allocator const &, container_allocator const &) noexcept { + return false; +} + +} // namespace mem +} // namespace ipc diff --git a/include/libipc/mem/memory_resource.h b/include/libipc/mem/memory_resource.h index 51b832c..0d2012f 100644 --- a/include/libipc/mem/memory_resource.h +++ b/include/libipc/mem/memory_resource.h @@ -11,7 +11,7 @@ #include "libipc/imp/export.h" #include "libipc/imp/span.h" #include "libipc/imp/byte.h" -#include "libipc/mem/polymorphic_allocator.h" +#include "libipc/mem/bytes_allocator.h" namespace ipc { namespace mem { diff --git a/src/libipc/mem/polymorphic_allocator.cpp b/src/libipc/mem/bytes_allocator.cpp similarity index 96% rename from src/libipc/mem/polymorphic_allocator.cpp rename to src/libipc/mem/bytes_allocator.cpp index 3b1383d..133f642 100644 --- a/src/libipc/mem/polymorphic_allocator.cpp +++ b/src/libipc/mem/bytes_allocator.cpp @@ -2,7 +2,7 @@ #include // std::swap #include "libipc/imp/log.h" -#include "libipc/mem/polymorphic_allocator.h" +#include "libipc/mem/bytes_allocator.h" #include "libipc/mem/memory_resource.h" namespace ipc { diff --git a/src/libipc/mem/central_cache_allocator.cpp b/src/libipc/mem/central_cache_allocator.cpp index 58be38b..d4a11b5 100644 --- a/src/libipc/mem/central_cache_allocator.cpp +++ b/src/libipc/mem/central_cache_allocator.cpp @@ -6,7 +6,7 @@ #include "libipc/def.h" #include "libipc/imp/detect_plat.h" #include "libipc/imp/byte.h" -#include "libipc/mem/polymorphic_allocator.h" +#include "libipc/mem/bytes_allocator.h" #include "libipc/mem/memory_resource.h" namespace ipc { diff --git a/src/libipc/mem/resource.h b/src/libipc/mem/resource.h index c864fe0..b519afb 100755 --- a/src/libipc/mem/resource.h +++ b/src/libipc/mem/resource.h @@ -6,7 +6,7 @@ #include "libipc/def.h" #include "libipc/imp/fmt.h" -#include "libipc/mem/polymorphic_allocator.h" +#include "libipc/mem/container_allocator.h" namespace ipc { @@ -15,12 +15,12 @@ struct hash : public std::hash {}; template using unordered_map = std::unordered_map< - Key, T, ipc::hash, std::equal_to, ipc::mem::polymorphic_allocator> + Key, T, ipc::hash, std::equal_to, ipc::mem::container_allocator> >; template using map = std::map< - Key, T, std::less, ipc::mem::polymorphic_allocator> + Key, T, std::less, ipc::mem::container_allocator> >; /// \brief Check string validity. diff --git a/test/mem/test_mem_allocator.cpp b/test/mem/test_mem_bytes_allocator.cpp similarity index 83% rename from test/mem/test_mem_allocator.cpp rename to test/mem/test_mem_bytes_allocator.cpp index 5702a07..05483f7 100644 --- a/test/mem/test_mem_allocator.cpp +++ b/test/mem/test_mem_bytes_allocator.cpp @@ -8,15 +8,15 @@ # include #endif -#include "libipc/mem/polymorphic_allocator.h" +#include "libipc/mem/bytes_allocator.h" #include "libipc/mem/memory_resource.h" -TEST(polymorphic_allocator, ctor) { +TEST(bytes_allocator, ctor) { ipc::mem::bytes_allocator alc; SUCCEED(); } -TEST(polymorphic_allocator, ctor_value_initialization) { +TEST(bytes_allocator, ctor_value_initialization) { ipc::mem::bytes_allocator alc{}; auto p = alc.allocate(128); EXPECT_NE(p, nullptr); @@ -37,14 +37,14 @@ public: } // namespace -TEST(polymorphic_allocator, memory_resource_traits) { +TEST(bytes_allocator, memory_resource_traits) { EXPECT_FALSE(ipc::mem::has_allocate::value); EXPECT_FALSE(ipc::mem::has_allocate::value); EXPECT_FALSE(ipc::mem::has_allocate>::value); EXPECT_FALSE(ipc::mem::has_allocate>::value); #if defined(LIBIMP_CPP_17) && defined(__cpp_lib_memory_resource) EXPECT_TRUE (ipc::mem::has_allocate::value); - EXPECT_TRUE (ipc::mem::has_allocate>::value); + EXPECT_TRUE (ipc::mem::has_allocate>::value); #endif EXPECT_FALSE(ipc::mem::has_deallocate::value); @@ -53,11 +53,11 @@ TEST(polymorphic_allocator, memory_resource_traits) { EXPECT_FALSE(ipc::mem::has_deallocate>::value); #if defined(LIBIMP_CPP_17) && defined(__cpp_lib_memory_resource) EXPECT_TRUE (ipc::mem::has_deallocate::value); - EXPECT_FALSE(ipc::mem::has_deallocate>::value); + EXPECT_FALSE(ipc::mem::has_deallocate>::value); #endif } -TEST(polymorphic_allocator, ctor_copy_move) { +TEST(bytes_allocator, ctor_copy_move) { ipc::mem::new_delete_resource mem_res; dummy_resource dummy_res; ipc::mem::bytes_allocator alc1{&mem_res}, alc2{&dummy_res}; @@ -79,7 +79,7 @@ TEST(polymorphic_allocator, ctor_copy_move) { ASSERT_NO_THROW(alc5.deallocate(p, 128)); } -TEST(polymorphic_allocator, swap) { +TEST(bytes_allocator, swap) { ipc::mem::new_delete_resource mem_res; dummy_resource dummy_res; ipc::mem::bytes_allocator alc1{&mem_res}, alc2{&dummy_res}; @@ -90,7 +90,7 @@ TEST(polymorphic_allocator, swap) { ASSERT_EQ(alc1.allocate(128), nullptr); } -TEST(polymorphic_allocator, invalid_alloc_free) { +TEST(bytes_allocator, invalid_alloc_free) { ipc::mem::bytes_allocator alc1; EXPECT_EQ(alc1.allocate(0), nullptr); EXPECT_NO_THROW(alc1.deallocate(nullptr, 128)); @@ -98,6 +98,6 @@ TEST(polymorphic_allocator, invalid_alloc_free) { EXPECT_NO_THROW(alc1.deallocate(&alc1, 0)); } -TEST(polymorphic_allocator, sizeof) { +TEST(bytes_allocator, sizeof) { EXPECT_EQ(sizeof(ipc::mem::bytes_allocator), sizeof(void *) * 2); }