mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
Fixed ut error on win.
This commit is contained in:
parent
a56a0cd643
commit
2d75c87672
@ -59,4 +59,17 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Rounds up the given value to the given alignment.
|
||||||
|
* \tparam T The type of the value.
|
||||||
|
* \param value The value to be rounded up.
|
||||||
|
* \param alignment The alignment to be rounded up to.
|
||||||
|
* \return The rounded up value.
|
||||||
|
* \see https://stackoverflow.com/questions/3407012/c-rounding-up-to-the-nearest-multiple-of-a-number
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
constexpr T round_up(T value, T alignment) noexcept {
|
||||||
|
return (value + alignment - 1) & ~(alignment - 1);
|
||||||
|
}
|
||||||
|
|
||||||
LIBIMP_NAMESPACE_END_
|
LIBIMP_NAMESPACE_END_
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
#include "libimp/uninitialized.h"
|
#include "libimp/uninitialized.h"
|
||||||
#include "libimp/byte.h"
|
#include "libimp/byte.h"
|
||||||
#include "libimp/generic.h"
|
#include "libimp/generic.h"
|
||||||
|
#include "libimp/aligned.h"
|
||||||
|
|
||||||
#include "libpmr/def.h"
|
#include "libpmr/def.h"
|
||||||
#include "libpmr/allocator.h"
|
#include "libpmr/allocator.h"
|
||||||
@ -80,14 +81,14 @@ class holder;
|
|||||||
template <typename Value>
|
template <typename Value>
|
||||||
class holder<Value, true> : public holder_base {
|
class holder<Value, true> : public holder_base {
|
||||||
|
|
||||||
alignas(alignof(Value)) std::array<::LIBIMP::byte, sizeof(Value)> value_storage_;
|
::LIBIMP::aligned<Value> value_storage_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
holder() = default; // uninitialized
|
holder() = default; // uninitialized
|
||||||
|
|
||||||
template <typename... A>
|
template <typename... A>
|
||||||
holder(allocator const &, A &&...args) {
|
holder(allocator const &, A &&...args) {
|
||||||
::LIBIMP::construct<Value>(value_storage_.data(), std::forward<A>(args)...);
|
::LIBIMP::construct<Value>(value_storage_.ptr(), std::forward<A>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool valid() const noexcept override {
|
bool valid() const noexcept override {
|
||||||
@ -111,11 +112,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *get() noexcept override {
|
void *get() noexcept override {
|
||||||
return value_storage_.data();
|
return value_storage_.ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
void const *get() const noexcept override {
|
void const *get() const noexcept override {
|
||||||
return value_storage_.data();
|
return value_storage_.ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
void move_to(allocator const &alloc, void *p) noexcept override {
|
void move_to(allocator const &alloc, void *p) noexcept override {
|
||||||
@ -226,16 +227,19 @@ void *holder_construct(allocator const &alloc, std::size_t n, Construct &&c) {
|
|||||||
class holder_info_ptr {
|
class holder_info_ptr {
|
||||||
allocator const &alloc_;
|
allocator const &alloc_;
|
||||||
holder_info **pptr_;
|
holder_info **pptr_;
|
||||||
|
std::size_t size_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
holder_info_ptr(allocator const &alloc, holder_info *(&ptr)) noexcept
|
holder_info_ptr(allocator const &alloc, holder_info *(&ptr), std::size_t sz) noexcept
|
||||||
: alloc_(alloc), pptr_(&ptr) {
|
: alloc_(alloc)
|
||||||
*pptr_ = static_cast<holder_info *>(alloc_.allocate(sizeof(holder_info), alignof(holder_info)));
|
, pptr_ (&ptr)
|
||||||
|
, size_ (::LIBIMP::round_up(sizeof(holder_info), alignof(std::max_align_t)) + sz) {
|
||||||
|
*pptr_ = static_cast<holder_info *>(alloc_.allocate(size_));
|
||||||
}
|
}
|
||||||
|
|
||||||
~holder_info_ptr() noexcept {
|
~holder_info_ptr() noexcept {
|
||||||
if (pptr_ == nullptr) return;
|
if (pptr_ == nullptr) return;
|
||||||
alloc_.deallocate(*pptr_, sizeof(holder_info), alignof(holder_info));
|
alloc_.deallocate(*pptr_, size_);
|
||||||
*pptr_ = nullptr;
|
*pptr_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,23 +360,19 @@ template <>
|
|||||||
class holder<void, false> : public holder_base {
|
class holder<void, false> : public holder_base {
|
||||||
|
|
||||||
detail::holder_info *info_ptr_;
|
detail::holder_info *info_ptr_;
|
||||||
void *value_ptr_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
holder() noexcept
|
holder() noexcept
|
||||||
: info_ptr_ (nullptr)
|
: info_ptr_ (nullptr){}
|
||||||
, value_ptr_(nullptr) {}
|
|
||||||
|
|
||||||
/// \brief Constructs a holder with type of `Value`.
|
/// \brief Constructs a holder with type of `Value`.
|
||||||
/// alignof(Value) must be less than or equal to alignof(std::max_align_t).
|
/// alignof(Value) must be less than or equal to alignof(std::max_align_t).
|
||||||
template <typename Value,
|
template <typename Value,
|
||||||
std::enable_if_t<alignof(Value) <= alignof(std::max_align_t), bool> = true>
|
std::enable_if_t<alignof(Value) <= alignof(std::max_align_t), bool> = true>
|
||||||
holder(allocator const &alloc, ::LIBIMP::types<Value>, std::size_t n) : holder() {
|
holder(allocator const &alloc, ::LIBIMP::types<Value>, std::size_t n) : holder() {
|
||||||
detail::holder_info_ptr info_p{alloc, info_ptr_};
|
detail::holder_info_ptr info_p{alloc, info_ptr_, sizeof(Value) * n};
|
||||||
if (!info_p) return;
|
if (!info_p) return;
|
||||||
value_ptr_ = detail::holder_construct<Value>(alloc, n,
|
::LIBIMP::uninitialized_default_construct_n(static_cast<Value *>(get()), n);
|
||||||
::LIBIMP::uninitialized_default_construct_n<Value *, std::size_t>);
|
|
||||||
if (value_ptr_ == nullptr) return;
|
|
||||||
info_p->type = &typeid(Value);
|
info_p->type = &typeid(Value);
|
||||||
info_p->sizeof_type = sizeof(Value);
|
info_p->sizeof_type = sizeof(Value);
|
||||||
info_p->count = n;
|
info_p->count = n;
|
||||||
@ -380,12 +380,9 @@ public:
|
|||||||
auto const &src = *static_cast<holder const *>(s);
|
auto const &src = *static_cast<holder const *>(s);
|
||||||
auto & dst = *::LIBIMP::construct<holder>(d);
|
auto & dst = *::LIBIMP::construct<holder>(d);
|
||||||
if (!src.valid()) return;
|
if (!src.valid()) return;
|
||||||
detail::holder_info_ptr info_p{alloc, dst.info_ptr_};
|
detail::holder_info_ptr info_p{alloc, dst.info_ptr_, sizeof(Value) * src.count()};
|
||||||
if (!info_p) return;
|
if (!info_p) return;
|
||||||
dst.value_ptr_ = detail::holder_construct<Value>(alloc, src.count(), [s = src.get()](Value *d, std::size_t n) {
|
::LIBIMP::uninitialized_default_construct_n(static_cast<Value *>(dst.get()), src.count());
|
||||||
std::uninitialized_copy_n(static_cast<Value const *>(s), n, d);
|
|
||||||
});
|
|
||||||
if (dst.value_ptr_ == nullptr) return;
|
|
||||||
*info_p = *src.info_ptr_;
|
*info_p = *src.info_ptr_;
|
||||||
info_p.release();
|
info_p.release();
|
||||||
};
|
};
|
||||||
@ -396,7 +393,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool valid() const noexcept override {
|
bool valid() const noexcept override {
|
||||||
return (value_ptr_ != nullptr) && (info_ptr_ != nullptr);
|
return info_ptr_ != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::type_info const &type() const noexcept override {
|
std::type_info const &type() const noexcept override {
|
||||||
@ -411,7 +408,8 @@ public:
|
|||||||
|
|
||||||
std::size_t sizeof_heap() const noexcept override {
|
std::size_t sizeof_heap() const noexcept override {
|
||||||
if (!valid()) return 0;
|
if (!valid()) return 0;
|
||||||
return info_ptr_->sizeof_type * info_ptr_->count + sizeof(detail::holder_info);
|
return ::LIBIMP::round_up(sizeof(detail::holder_info), alignof(std::max_align_t))
|
||||||
|
+ (info_ptr_->sizeof_type * info_ptr_->count);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t count() const noexcept override {
|
std::size_t count() const noexcept override {
|
||||||
@ -420,17 +418,18 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *get() noexcept override {
|
void *get() noexcept override {
|
||||||
return value_ptr_;
|
return reinterpret_cast<void *>(
|
||||||
|
::LIBIMP::round_up(reinterpret_cast<std::size_t>(info_ptr_ + 1), alignof(std::max_align_t)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void const *get() const noexcept override {
|
void const *get() const noexcept override {
|
||||||
return value_ptr_;
|
return reinterpret_cast<void const *>(
|
||||||
|
::LIBIMP::round_up(reinterpret_cast<std::size_t>(info_ptr_ + 1), alignof(std::max_align_t)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void move_to(allocator const &, void *p) noexcept override {
|
void move_to(allocator const &, void *p) noexcept override {
|
||||||
auto *des = ::LIBIMP::construct<holder>(p);
|
auto *des = ::LIBIMP::construct<holder>(p);
|
||||||
if (!valid()) return;
|
if (!valid()) return;
|
||||||
std::swap(value_ptr_, des->value_ptr_);
|
|
||||||
std::swap(info_ptr_, des->info_ptr_);
|
std::swap(info_ptr_, des->info_ptr_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,9 +441,105 @@ public:
|
|||||||
|
|
||||||
void destroy(allocator const &alloc) noexcept override {
|
void destroy(allocator const &alloc) noexcept override {
|
||||||
if (!valid()) return;
|
if (!valid()) return;
|
||||||
info_ptr_->dest (value_ptr_, count());
|
info_ptr_->dest(get(), count());
|
||||||
alloc.deallocate(value_ptr_, sizeof_heap());
|
alloc.deallocate(info_ptr_, sizeof_heap());
|
||||||
alloc.deallocate(info_ptr_ , sizeof(detail::holder_info), alignof(detail::holder_info));
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class small_storage
|
||||||
|
* \brief Unified SSO (Small Size Optimization).
|
||||||
|
* \tparam N The size of the storage.
|
||||||
|
*/
|
||||||
|
template <std::size_t N>
|
||||||
|
class small_storage {
|
||||||
|
|
||||||
|
static_assert(N > holder<int, false>, "N must be greater than sizeof(holder<int, false>)");
|
||||||
|
|
||||||
|
alignas(std::max_align_t) std::array<::LIBIMP::byte, N> storage_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
small_storage(small_storage const &) = delete;
|
||||||
|
small_storage &operator=(small_storage const &) = delete;
|
||||||
|
|
||||||
|
small_storage() noexcept {
|
||||||
|
::LIBIMP::construct<holder_null>(get_holder());
|
||||||
|
}
|
||||||
|
|
||||||
|
holder_base *get_holder() noexcept {
|
||||||
|
return static_cast<holder_base *>(storage_.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
holder_base const *get_holder() const noexcept {
|
||||||
|
return static_cast<holder_base const *>(storage_.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool valid() const noexcept {
|
||||||
|
return get_holder()->valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::type_info const &type() const noexcept {
|
||||||
|
return get_holder()->type();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t sizeof_type() const noexcept {
|
||||||
|
return get_holder()->sizeof_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t sizeof_heap() const noexcept {
|
||||||
|
return get_holder()->sizeof_heap();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t count() const noexcept {
|
||||||
|
return get_holder()->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
Value *As() noexcept {
|
||||||
|
return static_cast<Value *>(get_holder()->get());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
Value const *As() const noexcept {
|
||||||
|
return static_cast<Value const *>(get_holder()->get());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
Value &AsRef() noexcept {
|
||||||
|
return *As<Value>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
Value const &AsRef() const noexcept {
|
||||||
|
return *As<Value>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void move_to(allocator const &alloc, small_storage &des) noexcept {
|
||||||
|
get_holder()->move_to(alloc, des.get_holder());
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_to(allocator const &alloc, small_storage &des) const noexcept(false) {
|
||||||
|
get_holder()->copy_to(alloc, des.get_holder());
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(allocator const &alloc) noexcept {
|
||||||
|
if (!valid()) return;
|
||||||
|
get_holder()->destroy(alloc);
|
||||||
|
::LIBIMP::construct<holder_null>(get_holder());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value, typename... A>
|
||||||
|
Value *acquire(allocator const &alloc, ::LIBIMP::types<Value>, A &&...args) {
|
||||||
|
get_holder()->destroy(alloc);
|
||||||
|
constexpr bool on_stack = (sizeof(holder<Value, true>) <= N);
|
||||||
|
return ::LIBIMP::construct<holder<Value, on_stack>>(get_holder(), alloc, std::forward<A>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
Value *acquire(allocator const &alloc, ::LIBIMP::types<Value>, std::size_t n) {
|
||||||
|
get_holder()->destroy(alloc);
|
||||||
|
constexpr bool on_stack = (sizeof(holder<void, true>) <= N);
|
||||||
|
return ::LIBIMP::construct<holder<void, on_stack>>(get_holder(), alloc, ::LIBIMP::types<Value>{}, n);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -5,10 +5,10 @@
|
|||||||
#include "libimp/error.h"
|
#include "libimp/error.h"
|
||||||
#include "libimp/result.h"
|
#include "libimp/result.h"
|
||||||
#include "libimp/fmt.h"
|
#include "libimp/fmt.h"
|
||||||
|
#include "libimp/codecvt.h"
|
||||||
|
|
||||||
TEST(error, error_code) {
|
TEST(error, error_code) {
|
||||||
std::error_code ecode;
|
std::error_code ecode;
|
||||||
EXPECT_FALSE(ecode);
|
EXPECT_FALSE(ecode);
|
||||||
std::cout << ecode.message() << "\n";
|
std::cout << imp::fmt(ecode, '\n');
|
||||||
EXPECT_EQ(ecode.message(), "Success");
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -102,11 +102,11 @@ TEST(result, fmt) {
|
|||||||
imp::result<int *> r3 {&aaa};
|
imp::result<int *> r3 {&aaa};
|
||||||
EXPECT_EQ(imp::fmt(r3), imp::fmt("succ, value = ", (void *)&aaa));
|
EXPECT_EQ(imp::fmt(r3), imp::fmt("succ, value = ", (void *)&aaa));
|
||||||
imp::result<int *> r4 {nullptr};
|
imp::result<int *> r4 {nullptr};
|
||||||
EXPECT_EQ(imp::fmt(r4), imp::fmt("fail, value = ", nullptr, ", error = [-1: Unknown error -1]"));
|
EXPECT_EQ(imp::fmt(r4), imp::fmt("fail, value = ", nullptr, ", error = ", std::error_code(-1, std::generic_category())));
|
||||||
r4 = {nullptr, std::error_code{1234, std::generic_category()}};
|
r4 = std::error_code(1234, std::generic_category());
|
||||||
EXPECT_EQ(imp::fmt(r4), imp::fmt("fail, value = ", nullptr, ", error = [1234: Unknown error 1234]"));
|
EXPECT_EQ(imp::fmt(r4), imp::fmt("fail, value = ", nullptr, ", error = ", std::error_code(1234, std::generic_category())));
|
||||||
imp::result<int *> r5;
|
imp::result<int *> r5;
|
||||||
EXPECT_EQ(imp::fmt(r5), "fail, value = null, error = [-1: Unknown error -1]");
|
EXPECT_EQ(imp::fmt(r5), imp::fmt("fail, value = null, error = ", std::error_code(-1, std::generic_category())));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
imp::result<std::int64_t> r1 {-123};
|
imp::result<std::int64_t> r1 {-123};
|
||||||
@ -114,9 +114,9 @@ TEST(result, fmt) {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
imp::result<void> r1;
|
imp::result<void> r1;
|
||||||
EXPECT_EQ(imp::fmt(r1), "fail, error = [-1: Unknown error -1]");
|
EXPECT_EQ(imp::fmt(r1), imp::fmt("fail, error = ", std::error_code(-1, std::generic_category())));
|
||||||
r1 = std::error_code{};
|
r1 = std::error_code{};
|
||||||
EXPECT_TRUE(r1);
|
EXPECT_TRUE(r1);
|
||||||
EXPECT_EQ(imp::fmt(r1), "succ, error = [0: Success]");
|
EXPECT_EQ(imp::fmt(r1), imp::fmt("succ, error = ", std::error_code()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user