mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-07 01:06:45 +08:00
Fixed possible errors in memory allocation greater than 64K.
This commit is contained in:
parent
2a1d8fa5fa
commit
174d5e41df
@ -42,6 +42,7 @@
|
|||||||
# define LIBIMP_CC_MSVC_2015 1900
|
# define LIBIMP_CC_MSVC_2015 1900
|
||||||
# define LIBIMP_CC_MSVC_2017 1910
|
# define LIBIMP_CC_MSVC_2017 1910
|
||||||
# define LIBIMP_CC_MSVC_2019 1920
|
# define LIBIMP_CC_MSVC_2019 1920
|
||||||
|
# define LIBIMP_CC_MSVC_2022 1930
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
# define LIBIMP_CC_GNUC __GNUC__
|
# define LIBIMP_CC_GNUC __GNUC__
|
||||||
# if defined(__clang__)
|
# if defined(__clang__)
|
||||||
|
|||||||
@ -25,7 +25,7 @@ LIBPMR_NAMESPACE_BEG_
|
|||||||
class LIBIMP_EXPORT block_collector {
|
class LIBIMP_EXPORT block_collector {
|
||||||
public:
|
public:
|
||||||
virtual ~block_collector() noexcept = default;
|
virtual ~block_collector() noexcept = default;
|
||||||
virtual void deallocate(void *p) noexcept = 0;
|
virtual void recycle(void *p, std::size_t bytes, std::size_t alignment) noexcept = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
using get_block_collector_t = block_collector *(*)() noexcept;
|
using get_block_collector_t = block_collector *(*)() noexcept;
|
||||||
@ -60,15 +60,41 @@ constexpr inline std::size_t regular_sizeof() noexcept {
|
|||||||
return regular_sizeof_impl(regular_head_size + sizeof(T));
|
return regular_sizeof_impl(regular_head_size + sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Use block pools to handle memory less than 64K.
|
||||||
|
template <std::size_t BlockSize, std::size_t BlockPoolExpansion>
|
||||||
|
class block_resource_base : public block_pool<BlockSize, BlockPoolExpansion> {
|
||||||
|
public:
|
||||||
|
void *allocate(std::size_t /*bytes*/, std::size_t /*alignment*/) noexcept {
|
||||||
|
return block_pool<BlockSize, BlockPoolExpansion>::allocate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(void *p, std::size_t /*bytes*/, std::size_t /*alignment*/) noexcept {
|
||||||
|
block_pool<BlockSize, BlockPoolExpansion>::deallocate(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Use `new`/`delete` to handle memory larger than 64K.
|
||||||
|
template <std::size_t BlockSize>
|
||||||
|
class block_resource_base<BlockSize, 0> : public new_delete_resource {
|
||||||
|
public:
|
||||||
|
void *allocate(std::size_t bytes, std::size_t alignment) noexcept {
|
||||||
|
return new_delete_resource::allocate(regular_head_size + bytes, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(void *p, std::size_t bytes, std::size_t alignment) noexcept {
|
||||||
|
new_delete_resource::deallocate(p, regular_head_size + bytes, alignment);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// \brief Defines block pool memory resource based on block pool.
|
/// \brief Defines block pool memory resource based on block pool.
|
||||||
template <std::size_t BlockSize, std::size_t BlockPoolExpansion>
|
template <std::size_t BlockSize, std::size_t BlockPoolExpansion>
|
||||||
class block_pool_resource : public block_pool<BlockSize, BlockPoolExpansion>
|
class block_pool_resource : public block_resource_base<BlockSize, BlockPoolExpansion>
|
||||||
, public block_collector {
|
, public block_collector {
|
||||||
|
|
||||||
using base_t = block_pool<BlockSize, BlockPoolExpansion>;
|
using base_t = block_resource_base<BlockSize, BlockPoolExpansion>;
|
||||||
|
|
||||||
void deallocate(void *p) noexcept override {
|
void recycle(void *p, std::size_t bytes, std::size_t alignment) noexcept override {
|
||||||
base_t::deallocate(p);
|
base_t::deallocate(p, bytes, alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -77,22 +103,20 @@ public:
|
|||||||
return &instance;
|
return &instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
using base_t::base_t;
|
void *allocate(std::size_t bytes, std::size_t alignment = alignof(std::max_align_t)) noexcept {
|
||||||
|
void *p = base_t::allocate(bytes, alignment);
|
||||||
void *allocate(std::size_t /*bytes*/, std::size_t /*alignment*/ = alignof(std::max_align_t)) noexcept {
|
|
||||||
void *p = base_t::allocate();
|
|
||||||
*static_cast<get_block_collector_t *>(p) = get;
|
*static_cast<get_block_collector_t *>(p) = get;
|
||||||
return static_cast<::LIBIMP::byte *>(p) + regular_head_size;
|
return static_cast<::LIBIMP::byte *>(p) + regular_head_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deallocate(void *p, std::size_t /*bytes*/, std::size_t /*alignment*/ = alignof(std::max_align_t)) noexcept {
|
void deallocate(void *p, std::size_t bytes, std::size_t alignment = alignof(std::max_align_t)) noexcept {
|
||||||
p = static_cast<::LIBIMP::byte *>(p) - regular_head_size;
|
p = static_cast<::LIBIMP::byte *>(p) - regular_head_size;
|
||||||
auto g = *static_cast<get_block_collector_t *>(p);
|
auto g = *static_cast<get_block_collector_t *>(p);
|
||||||
if (g == get) {
|
if (g == get) {
|
||||||
base_t::deallocate(p);
|
base_t::deallocate(p, bytes, alignment);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g()->deallocate(p);
|
g()->recycle(p, bytes, alignment);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -115,9 +139,6 @@ struct regular_resource {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <std::size_t N>
|
|
||||||
struct regular_resource<N, 4> : new_delete_resource {};
|
|
||||||
|
|
||||||
/// \brief Creates an object based on the specified type and parameters with block pool resource.
|
/// \brief Creates an object based on the specified type and parameters with block pool resource.
|
||||||
/// \note This function is thread-safe.
|
/// \note This function is thread-safe.
|
||||||
template <typename T, typename... A>
|
template <typename T, typename... A>
|
||||||
@ -136,11 +157,11 @@ void delete$(T *p) noexcept {
|
|||||||
::LIBIMP::destroy(p);
|
::LIBIMP::destroy(p);
|
||||||
auto *res = regular_resource<regular_sizeof<T>()>::get();
|
auto *res = regular_resource<regular_sizeof<T>()>::get();
|
||||||
if (res == nullptr) return;
|
if (res == nullptr) return;
|
||||||
#if defined(LIBIMP_CC_MSVC_2015)
|
#if (LIBIMP_CC_MSVC > LIBIMP_CC_MSVC_2015)
|
||||||
|
res->deallocate(p, sizeof(T), alignof(T));
|
||||||
|
#else
|
||||||
// `alignof` of vs2015 requires that type must be able to be instantiated.
|
// `alignof` of vs2015 requires that type must be able to be instantiated.
|
||||||
res->deallocate(p, sizeof(T));
|
res->deallocate(p, sizeof(T));
|
||||||
#else
|
|
||||||
res->deallocate(p, sizeof(T), alignof(T));
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -93,6 +93,14 @@ private:
|
|||||||
int value_;
|
int value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Derived64K : public Derived {
|
||||||
|
public:
|
||||||
|
using Derived::Derived;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<char, 65536> padding_;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST(pmr_new, delete$poly) {
|
TEST(pmr_new, delete$poly) {
|
||||||
@ -110,6 +118,21 @@ TEST(pmr_new, delete$poly) {
|
|||||||
ASSERT_EQ(construct_count__, 0);
|
ASSERT_EQ(construct_count__, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(pmr_new, delete$poly64k) {
|
||||||
|
Base *p = pmr::new$<Derived64K>(-1);
|
||||||
|
ASSERT_NE(p, nullptr);
|
||||||
|
ASSERT_EQ(p->get(), -1);
|
||||||
|
ASSERT_EQ(construct_count__, -1);
|
||||||
|
pmr::delete$(p);
|
||||||
|
ASSERT_EQ(construct_count__, 0);
|
||||||
|
|
||||||
|
Base *q = pmr::new$<Derived64K>((std::numeric_limits<int>::max)());
|
||||||
|
ASSERT_EQ(q->get(), (std::numeric_limits<int>::max)());
|
||||||
|
ASSERT_EQ(construct_count__, (std::numeric_limits<int>::max)());
|
||||||
|
pmr::delete$(q);
|
||||||
|
ASSERT_EQ(construct_count__, 0);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(pmr_new, delete$null) {
|
TEST(pmr_new, delete$null) {
|
||||||
Base *p = nullptr;
|
Base *p = nullptr;
|
||||||
pmr::delete$(p);
|
pmr::delete$(p);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user