mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
upd: [pmr] optimize allocator implementation
This commit is contained in:
parent
774a3c9af7
commit
cd545653c4
@ -77,18 +77,15 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
data *init(index_t circ_size) noexcept {
|
data *init(index_t circ_size) noexcept {
|
||||||
if (!data_allocator_) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
void *data_ptr = nullptr;
|
void *data_ptr = nullptr;
|
||||||
LIBIMP_TRY {
|
LIBIMP_TRY {
|
||||||
data_ptr = data_allocator_.alloc(data::size_of(circ_size));
|
data_ptr = data_allocator_.allocate(data::size_of(circ_size));
|
||||||
if (data_ptr == nullptr) {
|
if (data_ptr == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return ::LIBIMP::construct<data>(data_ptr, circ_size);
|
return ::LIBIMP::construct<data>(data_ptr, circ_size);
|
||||||
} LIBIMP_CATCH(...) {
|
} LIBIMP_CATCH(...) {
|
||||||
data_allocator_.dealloc(data_ptr, data::size_of(circ_size));
|
data_allocator_.deallocate(data_ptr, data::size_of(circ_size));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,7 +125,7 @@ public:
|
|||||||
if (valid()) {
|
if (valid()) {
|
||||||
auto sz = data_->byte_size();
|
auto sz = data_->byte_size();
|
||||||
(void)::LIBIMP::destroy<data>(data_);
|
(void)::LIBIMP::destroy<data>(data_);
|
||||||
data_allocator_.dealloc(data_, sz);
|
data_allocator_.deallocate(data_, sz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +145,7 @@ public:
|
|||||||
: data_model(default_circle_buffer_size) {}
|
: data_model(default_circle_buffer_size) {}
|
||||||
|
|
||||||
bool valid() const noexcept {
|
bool valid() const noexcept {
|
||||||
return (data_ != nullptr) && data_allocator_.valid();
|
return data_ != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit operator bool() const noexcept {
|
explicit operator bool() const noexcept {
|
||||||
|
|||||||
@ -44,8 +44,7 @@ class byte {
|
|||||||
std::uint8_t bits_;
|
std::uint8_t bits_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr byte() noexcept
|
byte() noexcept = default;
|
||||||
: byte(0) {}
|
|
||||||
|
|
||||||
template <typename T, typename = detail::is_integral<T>>
|
template <typename T, typename = detail::is_integral<T>>
|
||||||
constexpr byte(T v) noexcept
|
constexpr byte(T v) noexcept
|
||||||
|
|||||||
@ -32,63 +32,54 @@ LIBPMR_NAMESPACE_BEG_
|
|||||||
*/
|
*/
|
||||||
class LIBIMP_EXPORT allocator {
|
class LIBIMP_EXPORT allocator {
|
||||||
|
|
||||||
class holder_base {
|
class holder_mr_base {
|
||||||
public:
|
public:
|
||||||
virtual ~holder_base() noexcept = default;
|
virtual ~holder_mr_base() noexcept = default;
|
||||||
virtual void *alloc(std::size_t) = 0;
|
virtual void *alloc(std::size_t, std::size_t) const = 0;
|
||||||
virtual void dealloc(void *, std::size_t) = 0;
|
virtual void dealloc(void *, std::size_t, std::size_t) const = 0;
|
||||||
virtual bool valid() const noexcept = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class holder_null : public holder_base {
|
template <typename MR, typename = bool>
|
||||||
public:
|
class holder_mr;
|
||||||
void *alloc(std::size_t) override { return nullptr; }
|
|
||||||
void dealloc(void *, std::size_t) override {}
|
|
||||||
bool valid() const noexcept override { return false; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename MemRes, typename = bool>
|
|
||||||
class holder_memory_resource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief A memory resource pointer holder class for type erasure.
|
|
||||||
* \tparam MR memory resource type
|
|
||||||
*/
|
|
||||||
template <typename MR>
|
|
||||||
class holder_memory_resource<MR, verify_memory_resource<MR>> : public holder_base {
|
|
||||||
MR *p_mem_res_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
holder_memory_resource(MR *p_mr) noexcept
|
|
||||||
: p_mem_res_(p_mr) {}
|
|
||||||
|
|
||||||
void *alloc(std::size_t s) override {
|
|
||||||
return p_mem_res_->allocate(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dealloc(void *p, std::size_t s) override {
|
|
||||||
p_mem_res_->deallocate(p, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool valid() const noexcept override {
|
|
||||||
return p_mem_res_ != nullptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief An empty holding class used to calculate a reasonable memory size for the holder.
|
* \brief An empty holding class used to calculate a reasonable memory size for the holder.
|
||||||
* \tparam MR cannot be converted to the type of memory resource
|
* \tparam MR cannot be converted to the type of memory resource
|
||||||
*/
|
*/
|
||||||
template <typename MR, typename U>
|
template <typename MR, typename U>
|
||||||
class holder_memory_resource : public holder_null {
|
class holder_mr : public holder_mr_base {
|
||||||
MR *p_dummy_;
|
protected:
|
||||||
|
MR *res_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
holder_mr(MR *p_mr) noexcept
|
||||||
|
: res_(p_mr) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
using void_holder_type = holder_memory_resource<void>;
|
/**
|
||||||
alignas(void_holder_type) std::array<::LIBIMP::byte, sizeof(void_holder_type)> holder_;
|
* \brief A memory resource pointer holder class for type erasure.
|
||||||
|
* \tparam MR memory resource type
|
||||||
|
*/
|
||||||
|
template <typename MR>
|
||||||
|
class holder_mr<MR, verify_memory_resource<MR>> : public holder_mr<MR, void> {
|
||||||
|
public:
|
||||||
|
holder_mr(MR *p_mr) noexcept
|
||||||
|
: holder_mr<MR, void>{p_mr} {}
|
||||||
|
|
||||||
holder_base & get_holder() noexcept;
|
void *alloc(std::size_t s, std::size_t a) const override {
|
||||||
holder_base const &get_holder() const noexcept;
|
return res_->allocate(s, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dealloc(void *p, std::size_t s, std::size_t a) const override {
|
||||||
|
res_->deallocate(p, s, a);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using void_holder_t = holder_mr<void *>;
|
||||||
|
alignas(void_holder_t) std::array<::LIBIMP::byte, sizeof(void_holder_t)> holder_;
|
||||||
|
|
||||||
|
holder_mr_base & get_holder() noexcept;
|
||||||
|
holder_mr_base const &get_holder() const noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
allocator() noexcept;
|
allocator() noexcept;
|
||||||
@ -97,24 +88,25 @@ public:
|
|||||||
allocator(allocator const &other) noexcept = default;
|
allocator(allocator const &other) noexcept = default;
|
||||||
allocator &operator=(allocator const &other) & noexcept = default;
|
allocator &operator=(allocator const &other) & noexcept = default;
|
||||||
|
|
||||||
allocator(allocator &&other) noexcept;
|
allocator(allocator &&other) noexcept = default;
|
||||||
allocator &operator=(allocator &&other) & noexcept;
|
allocator &operator=(allocator &&other) & noexcept = default;
|
||||||
|
|
||||||
/// \brief Constructs a allocator from a memory resource pointer
|
/// \brief Constructs a allocator from a memory resource pointer
|
||||||
/// The lifetime of the pointer must be longer than that of allocator.
|
/// The lifetime of the pointer must be longer than that of allocator.
|
||||||
template <typename T, verify_memory_resource<T> = true>
|
template <typename T, verify_memory_resource<T> = true>
|
||||||
allocator(T *p_mr) : allocator() {
|
allocator(T *p_mr) noexcept {
|
||||||
if (p_mr == nullptr) return;
|
if (p_mr == nullptr) {
|
||||||
::LIBIMP::construct<holder_memory_resource<T>>(holder_.data(), p_mr);
|
::LIBIMP::construct<holder_mr<new_delete_resource>>(holder_.data(), new_delete_resource::get());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
::LIBIMP::construct<holder_mr<T>>(holder_.data(), p_mr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(allocator &other) noexcept;
|
void swap(allocator &other) noexcept;
|
||||||
bool valid() const noexcept;
|
|
||||||
explicit operator bool() const noexcept;
|
|
||||||
|
|
||||||
/// \brief Allocate/deallocate memory.
|
/// \brief Allocate/deallocate memory.
|
||||||
void *alloc(std::size_t s);
|
void *allocate(std::size_t s, std::size_t = alignof(std::max_align_t)) const;
|
||||||
void dealloc(void *p, std::size_t s);
|
void deallocate(void *p, std::size_t s, std::size_t = alignof(std::max_align_t)) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
LIBPMR_NAMESPACE_END_
|
LIBPMR_NAMESPACE_END_
|
||||||
|
|||||||
122
include/libpmr/holder_base.h
Normal file
122
include/libpmr/holder_base.h
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/**
|
||||||
|
* \file libpmr/small_storage.h
|
||||||
|
* \author mutouyun (orz@orzz.org)
|
||||||
|
* \brief Unified SSO (Small Size Optimization) holder base.
|
||||||
|
* \date 2023-09-02
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <array>
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <utility>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include "libimp/export.h"
|
||||||
|
#include "libimp/construct.h"
|
||||||
|
#include "libimp/byte.h"
|
||||||
|
#include "libimp/generic.h"
|
||||||
|
|
||||||
|
#include "libpmr/def.h"
|
||||||
|
|
||||||
|
LIBPMR_NAMESPACE_BEG_
|
||||||
|
|
||||||
|
class LIBIMP_EXPORT allocator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class holder_base
|
||||||
|
* \brief Data holder base class.
|
||||||
|
*/
|
||||||
|
class holder_base {
|
||||||
|
public:
|
||||||
|
virtual ~holder_base() noexcept = default;
|
||||||
|
virtual bool valid() const noexcept = 0;
|
||||||
|
virtual std::type_info const &type() const noexcept = 0;
|
||||||
|
virtual std::size_t sizeof_type() const noexcept = 0;
|
||||||
|
virtual std::size_t count() const noexcept = 0;
|
||||||
|
virtual std::size_t size () const noexcept = 0;
|
||||||
|
virtual void *get() noexcept = 0;
|
||||||
|
virtual void const *get() const noexcept = 0;
|
||||||
|
virtual void move_to(allocator const &, void *) noexcept = 0;
|
||||||
|
virtual void copy_to(allocator const &, void *) const noexcept(false) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class holder_null
|
||||||
|
* \brief A holder implementation that does not hold any data objects.
|
||||||
|
*/
|
||||||
|
class holder_null : public holder_base {
|
||||||
|
public:
|
||||||
|
bool valid() const noexcept override { return false; }
|
||||||
|
std::type_info const &type() const noexcept override { return typeid(nullptr);}
|
||||||
|
std::size_t sizeof_type() const noexcept override { return 0; }
|
||||||
|
std::size_t count() const noexcept override { return 0; }
|
||||||
|
std::size_t size () const noexcept override { return 0; }
|
||||||
|
void *get() noexcept override { return nullptr; }
|
||||||
|
void const *get() const noexcept override { return nullptr; }
|
||||||
|
|
||||||
|
/// \brief The passed destination pointer is never null,
|
||||||
|
/// and the memory to which it points is uninitialized.
|
||||||
|
void move_to(allocator const &, void *) noexcept override {}
|
||||||
|
void copy_to(allocator const &, void *) const noexcept(false) override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Value, bool/*is on stack*/>
|
||||||
|
class holder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class template <typename Value> holder<Value, true>
|
||||||
|
* \brief A holder implementation that holds a data object if type `Value` on stack memory.
|
||||||
|
* \tparam Value The storage type of the holder.
|
||||||
|
*/
|
||||||
|
template <typename Value>
|
||||||
|
class holder<Value, true> : public holder_base {
|
||||||
|
|
||||||
|
alignas(alignof(Value)) std::array<::LIBIMP::byte, sizeof(Value)> value_storage_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
holder() = default; // uninitialized
|
||||||
|
|
||||||
|
template <typename... A>
|
||||||
|
holder(::LIBIMP::in_place_t, A &&...args) {
|
||||||
|
::LIBIMP::construct<Value>(value_storage_.data(), std::forward<A>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool valid() const noexcept override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::type_info const &type() const noexcept override {
|
||||||
|
return typeid(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t sizeof_type() const noexcept override {
|
||||||
|
return sizeof(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t count() const noexcept override {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t size() const noexcept override {
|
||||||
|
return value_storage_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void *get() noexcept override {
|
||||||
|
return value_storage_.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
void const *get() const noexcept override {
|
||||||
|
return value_storage_.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
void move_to(allocator const &, void *p) noexcept override {
|
||||||
|
::LIBIMP::construct<holder>(p, ::LIBIMP::in_place, std::move(*static_cast<Value *>(get())));
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_to(allocator const &, void *p) const noexcept(false) override {
|
||||||
|
::LIBIMP::construct<holder>(p, ::LIBIMP::in_place, *static_cast<Value *>(get()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
LIBPMR_NAMESPACE_END_
|
||||||
35
include/libpmr/small_storage.h
Normal file
35
include/libpmr/small_storage.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* \file libpmr/small_storage.h
|
||||||
|
* \author mutouyun (orz@orzz.org)
|
||||||
|
* \brief Unified SSO (Small Size Optimization).
|
||||||
|
* \date 2023-09-02
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <array>
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <utility>
|
||||||
|
#include <memory>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include "libimp/export.h"
|
||||||
|
#include "libimp/construct.h"
|
||||||
|
#include "libimp/byte.h"
|
||||||
|
#include "libimp/generic.h"
|
||||||
|
|
||||||
|
#include "libpmr/def.h"
|
||||||
|
#include "libpmr/holder_base.h"
|
||||||
|
|
||||||
|
LIBPMR_NAMESPACE_BEG_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class template <typename Value> holder<Value, false>
|
||||||
|
* \brief A holder implementation that holds a data object if type `Value` on heap memory.
|
||||||
|
* \tparam Value The storage type of the holder.
|
||||||
|
*/
|
||||||
|
template <typename Value>
|
||||||
|
class holder<Value, false> : public holder_base {
|
||||||
|
};
|
||||||
|
|
||||||
|
LIBPMR_NAMESPACE_END_
|
||||||
@ -5,54 +5,31 @@
|
|||||||
|
|
||||||
LIBPMR_NAMESPACE_BEG_
|
LIBPMR_NAMESPACE_BEG_
|
||||||
|
|
||||||
allocator::holder_base &allocator::get_holder() noexcept {
|
allocator::holder_mr_base &allocator::get_holder() noexcept {
|
||||||
return *reinterpret_cast<holder_base *>(holder_.data());
|
return *reinterpret_cast<holder_mr_base *>(holder_.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
allocator::holder_base const &allocator::get_holder() const noexcept {
|
allocator::holder_mr_base const &allocator::get_holder() const noexcept {
|
||||||
return *reinterpret_cast<holder_base const *>(holder_.data());
|
return *reinterpret_cast<holder_mr_base const *>(holder_.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
allocator::allocator() noexcept {
|
allocator::allocator() noexcept
|
||||||
::LIBIMP::construct<holder_null>(holder_.data());
|
: allocator(new_delete_resource::get()) {}
|
||||||
}
|
|
||||||
|
|
||||||
allocator::~allocator() noexcept {
|
allocator::~allocator() noexcept {
|
||||||
::LIBIMP::destroy(&get_holder());
|
::LIBIMP::destroy(&get_holder());
|
||||||
}
|
}
|
||||||
|
|
||||||
allocator::allocator(allocator &&other) noexcept
|
|
||||||
: allocator(other) /*copy*/ {
|
|
||||||
::LIBIMP::construct<holder_null>(other.holder_.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
allocator &allocator::operator=(allocator &&other) & noexcept {
|
|
||||||
if (this == &other) return *this;
|
|
||||||
this->holder_ = other.holder_;
|
|
||||||
::LIBIMP::construct<holder_null>(other.holder_.data());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void allocator::swap(allocator &other) noexcept {
|
void allocator::swap(allocator &other) noexcept {
|
||||||
std::swap(this->holder_, other.holder_);
|
std::swap(this->holder_, other.holder_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool allocator::valid() const noexcept {
|
void *allocator::allocate(std::size_t s, std::size_t a) const {
|
||||||
return get_holder().valid();
|
return get_holder().alloc(s, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
allocator::operator bool() const noexcept {
|
void allocator::deallocate(void *p, std::size_t s, std::size_t a) const {
|
||||||
return valid();
|
get_holder().dealloc(p, s, a);
|
||||||
}
|
|
||||||
|
|
||||||
void *allocator::alloc(std::size_t s) {
|
|
||||||
if (!valid()) return nullptr;
|
|
||||||
return get_holder().alloc(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void allocator::dealloc(void *p, std::size_t s) {
|
|
||||||
if (!valid()) return;
|
|
||||||
get_holder().dealloc(p, s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBPMR_NAMESPACE_END_
|
LIBPMR_NAMESPACE_END_
|
||||||
|
|||||||
@ -8,71 +8,71 @@
|
|||||||
|
|
||||||
TEST(allocator, construct) {
|
TEST(allocator, construct) {
|
||||||
pmr::allocator alc;
|
pmr::allocator alc;
|
||||||
EXPECT_FALSE(alc.valid());
|
SUCCEED();
|
||||||
EXPECT_FALSE(alc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(allocator, construct_with_memory_resource) {
|
TEST(allocator, construct_value_initialization) {
|
||||||
pmr::new_delete_resource mem_res;
|
pmr::allocator alc{};
|
||||||
pmr::allocator alc {&mem_res};
|
auto p = alc.allocate(128);
|
||||||
EXPECT_TRUE(alc.valid());
|
|
||||||
EXPECT_TRUE(alc);
|
|
||||||
|
|
||||||
auto p = alc.alloc(128);
|
|
||||||
EXPECT_NE(p, nullptr);
|
EXPECT_NE(p, nullptr);
|
||||||
EXPECT_NO_THROW(alc.dealloc(p, 128));
|
EXPECT_NO_THROW(alc.deallocate(p, 128));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class dummy_resource {
|
||||||
|
public:
|
||||||
|
void *allocate(std::size_t, std::size_t = 0) noexcept {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
void deallocate(void *, std::size_t, std::size_t = 0) noexcept {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
TEST(allocator, construct_copy_move) {
|
TEST(allocator, construct_copy_move) {
|
||||||
pmr::new_delete_resource mem_res;
|
pmr::new_delete_resource mem_res;
|
||||||
|
dummy_resource dummy_res;
|
||||||
pmr::allocator alc1 {&mem_res}, alc2;
|
pmr::allocator alc1{&mem_res}, alc2{&dummy_res};
|
||||||
EXPECT_TRUE (alc1.valid());
|
auto p = alc1.allocate(128);
|
||||||
EXPECT_TRUE (alc1);
|
ASSERT_NE(p, nullptr);
|
||||||
EXPECT_FALSE(alc2.valid());
|
ASSERT_NO_THROW(alc1.deallocate(p, 128));
|
||||||
EXPECT_FALSE(alc2);
|
ASSERT_EQ(alc2.allocate(128), nullptr);
|
||||||
|
|
||||||
pmr::allocator alc3{alc1}, alc4{alc2}, alc5{std::move(alc1)};
|
pmr::allocator alc3{alc1}, alc4{alc2}, alc5{std::move(alc1)};
|
||||||
EXPECT_TRUE (alc3.valid());
|
|
||||||
EXPECT_TRUE (alc3);
|
p = alc3.allocate(128);
|
||||||
EXPECT_FALSE(alc4.valid());
|
ASSERT_NE(p, nullptr);
|
||||||
EXPECT_FALSE(alc4);
|
ASSERT_NO_THROW(alc3.deallocate(p, 128));
|
||||||
EXPECT_TRUE (alc5.valid());
|
|
||||||
EXPECT_TRUE (alc5);
|
ASSERT_EQ(alc4.allocate(128), nullptr);
|
||||||
EXPECT_FALSE(alc1.valid());
|
|
||||||
EXPECT_FALSE(alc1);
|
p = alc5.allocate(128);
|
||||||
|
ASSERT_NE(p, nullptr);
|
||||||
|
ASSERT_NO_THROW(alc5.deallocate(p, 128));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(allocator, swap) {
|
TEST(allocator, swap) {
|
||||||
pmr::new_delete_resource mem_res;
|
pmr::new_delete_resource mem_res;
|
||||||
|
dummy_resource dummy_res;
|
||||||
pmr::allocator alc1 {&mem_res}, alc2;
|
pmr::allocator alc1{&mem_res}, alc2{&dummy_res};
|
||||||
EXPECT_TRUE (alc1.valid());
|
|
||||||
EXPECT_TRUE (alc1);
|
|
||||||
EXPECT_FALSE(alc2.valid());
|
|
||||||
EXPECT_FALSE(alc2);
|
|
||||||
|
|
||||||
alc1.swap(alc2);
|
alc1.swap(alc2);
|
||||||
EXPECT_FALSE(alc1.valid());
|
auto p = alc2.allocate(128);
|
||||||
EXPECT_FALSE(alc1);
|
ASSERT_NE(p, nullptr);
|
||||||
EXPECT_TRUE (alc2.valid());
|
ASSERT_NO_THROW(alc2.deallocate(p, 128));
|
||||||
EXPECT_TRUE (alc2);
|
ASSERT_EQ(alc1.allocate(128), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(allocator, invalid_alloc_free) {
|
TEST(allocator, invalid_alloc_free) {
|
||||||
pmr::new_delete_resource mem_res;
|
pmr::allocator alc1;
|
||||||
|
EXPECT_EQ(alc1.allocate(0), nullptr);
|
||||||
pmr::allocator alc1 {&mem_res}, alc2;
|
EXPECT_NO_THROW(alc1.deallocate(nullptr, 128));
|
||||||
EXPECT_EQ(alc1.alloc(0), nullptr);
|
EXPECT_NO_THROW(alc1.deallocate(nullptr, 0));
|
||||||
EXPECT_NO_THROW(alc1.dealloc(nullptr, 128));
|
EXPECT_NO_THROW(alc1.deallocate(&alc1, 0));
|
||||||
EXPECT_NO_THROW(alc1.dealloc(nullptr, 0));
|
}
|
||||||
EXPECT_NO_THROW(alc1.dealloc(&alc1, 0));
|
|
||||||
|
TEST(allocator, sizeof) {
|
||||||
EXPECT_EQ(alc2.alloc(0), nullptr);
|
EXPECT_EQ(sizeof(pmr::allocator), sizeof(void *) * 2);
|
||||||
EXPECT_NO_THROW(alc2.dealloc(nullptr, 128));
|
|
||||||
EXPECT_NO_THROW(alc2.dealloc(nullptr, 0));
|
|
||||||
EXPECT_NO_THROW(alc2.dealloc(&alc1, 0));
|
|
||||||
|
|
||||||
EXPECT_EQ(alc2.alloc(1024), nullptr);
|
|
||||||
EXPECT_NO_THROW(alc2.dealloc(&alc1, sizeof(alc1)));
|
|
||||||
}
|
}
|
||||||
7
test/pmr/test_pmr_small_storage.cpp
Normal file
7
test/pmr/test_pmr_small_storage.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#include "libpmr/small_storage.h"
|
||||||
|
|
||||||
|
TEST(small_storage, construct) {
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user