From 831225f763e21ed572d4657de30942df7fc3d511 Mon Sep 17 00:00:00 2001 From: mutouyun Date: Tue, 4 Feb 2025 10:33:13 +0800 Subject: [PATCH] Use `$new` instead of `alloc` --- include/libipc/mem/new.h | 5 +- include/libipc/pool_alloc.h | 103 ------ src/libipc/ipc.cpp | 27 +- src/libipc/mem/resource.h | 12 - src/libipc/memory/alloc.h | 423 ----------------------- src/libipc/memory/wrapper.h | 327 ------------------ src/libipc/platform/posix/shm_posix.cpp | 6 +- src/libipc/platform/win/shm_win.cpp | 6 +- src/libipc/pool_alloc.cpp | 17 - src/libipc/utility/pimpl.h | 6 +- test/mem/test_mem_allocator.cpp | 6 +- test/mem/test_mem_central_cache_pool.cpp | 16 +- test/test_ipc.cpp | 18 +- 13 files changed, 48 insertions(+), 924 deletions(-) delete mode 100755 include/libipc/pool_alloc.h delete mode 100755 src/libipc/memory/alloc.h delete mode 100755 src/libipc/memory/wrapper.h delete mode 100755 src/libipc/pool_alloc.cpp diff --git a/include/libipc/mem/new.h b/include/libipc/mem/new.h index fcd8223..0145854 100644 --- a/include/libipc/mem/new.h +++ b/include/libipc/mem/new.h @@ -26,7 +26,7 @@ namespace mem { class LIBIPC_EXPORT block_collector { public: virtual ~block_collector() noexcept = default; - virtual void recycle(void *p) noexcept = 0; + virtual void recycle(void */*p*/) noexcept {} }; #if defined(LIBIPC_CPP_17) @@ -182,8 +182,7 @@ T *$new(A &&... args) noexcept { /// \brief Destroys object previously allocated by the `$new` and releases obtained memory area. /// \note This function is thread-safe. If the pointer type passed in is different from `$new`, /// additional performance penalties may be incurred. -template -void $delete(T *p) noexcept { +inline void $delete(void *p) noexcept { if (p == nullptr) return; auto *b = reinterpret_cast(p) - regular_head_size; auto *r = reinterpret_cast(b); diff --git a/include/libipc/pool_alloc.h b/include/libipc/pool_alloc.h deleted file mode 100755 index 7ae299c..0000000 --- a/include/libipc/pool_alloc.h +++ /dev/null @@ -1,103 +0,0 @@ -#pragma once - -#include -#include - -#include "libipc/imp/export.h" -#include "libipc/def.h" - -namespace ipc { -namespace mem { - -class LIBIPC_EXPORT pool_alloc { -public: - static void* alloc(std::size_t size) noexcept; - static void free (void* p, std::size_t size) noexcept; -}; - -//////////////////////////////////////////////////////////////// -/// construct/destruct an object -//////////////////////////////////////////////////////////////// - -namespace detail { - -template -struct impl { - template - static T* construct(T* p, P&&... params) { - ::new (p) T(std::forward

(params)...); - return p; - } - - static void destruct(T* p) { - reinterpret_cast(p)->~T(); - } -}; - -template -struct impl { - using type = T[N]; - - template - static type* construct(type* p, P&&... params) { - for (size_t i = 0; i < N; ++i) { - impl::construct(&((*p)[i]), std::forward

(params)...); - } - return p; - } - - static void destruct(type* p) { - for (size_t i = 0; i < N; ++i) { - impl::destruct(&((*p)[i])); - } - } -}; - -} // namespace detail - -template -T* construct(T* p, P&&... params) { - return detail::impl::construct(p, std::forward

(params)...); -} - -template -T* construct(void* p, P&&... params) { - return construct(static_cast(p), std::forward

(params)...); -} - -template -void destruct(T* p) { - return detail::impl::destruct(p); -} - -template -void destruct(void* p) { - destruct(static_cast(p)); -} - -//////////////////////////////////////////////////////////////// -/// general alloc/free -//////////////////////////////////////////////////////////////// - -inline void* alloc(std::size_t size) { - return pool_alloc::alloc(size); -} - -template -T* alloc(P&&... params) { - return construct(pool_alloc::alloc(sizeof(T)), std::forward

(params)...); -} - -inline void free(void* p, std::size_t size) { - pool_alloc::free(p, size); -} - -template -void free(T* p) { - if (p == nullptr) return; - destruct(p); - pool_alloc::free(p, sizeof(T)); -} - -} // namespace mem -} // namespace ipc diff --git a/src/libipc/ipc.cpp b/src/libipc/ipc.cpp index 2b8ed35..4316e36 100755 --- a/src/libipc/ipc.cpp +++ b/src/libipc/ipc.cpp @@ -14,7 +14,6 @@ #include "libipc/ipc.h" #include "libipc/def.h" #include "libipc/shm.h" -#include "libipc/pool_alloc.h" #include "libipc/queue.h" #include "libipc/policy.h" #include "libipc/rw_lock.h" @@ -26,6 +25,7 @@ #include "libipc/utility/utility.h" #include "libipc/mem/resource.h" +#include "libipc/mem/new.h" #include "libipc/platform/detail.h" #include "libipc/circ/elem_array.h" @@ -64,10 +64,15 @@ struct msg_t : msg_t<0, AlignSize> { }; template -ipc::buff_t make_cache(T& data, std::size_t size) { - auto ptr = ipc::mem::alloc(size); +ipc::buff_t make_cache(T &data, std::size_t size) { + auto *ptr = ipc::mem::$new(size); std::memcpy(ptr, &data, (ipc::detail::min)(sizeof(data), size)); - return { ptr, size, ipc::mem::free }; + return { + ptr, size, + [](void *p, std::size_t) noexcept { + ipc::mem::$delete(p); + } + }; } acc_t *cc_acc(std::string const &pref) { @@ -259,8 +264,8 @@ chunk_info_t *chunk_storage_info(conn_info_head *inf, std::size_t chunk_size) { guard.unlock(); LIBIPC_UNUSED std::lock_guard guard {lock}; it = storages.emplace(chunk_size, chunk_handle_ptr_t{ - ipc::mem::alloc(), [](chunk_handle_t *p) { - ipc::mem::destruct(p); + ipc::mem::$new(), [](chunk_handle_t *p) { + ipc::mem::$delete(p); }}).first; } } @@ -447,7 +452,7 @@ constexpr static queue_t* queue_of(ipc::handle_t h) noexcept { static bool connect(ipc::handle_t * ph, ipc::prefix pref, char const * name, bool start_to_recv) { assert(ph != nullptr); if (*ph == nullptr) { - *ph = ipc::mem::alloc(pref.str, name); + *ph = ipc::mem::$new(pref.str, name); } return reconnect(ph, start_to_recv); } @@ -490,7 +495,7 @@ static bool reconnect(ipc::handle_t * ph, bool start_to_recv) { } static void destroy(ipc::handle_t h) noexcept { - ipc::mem::free(info_of(h)); + ipc::mem::$delete(info_of(h)); } static std::size_t recv_count(ipc::handle_t h) noexcept { @@ -654,20 +659,20 @@ static ipc::buff_t recv(ipc::handle_t h, std::uint64_t tm) { conn_info_t * inf; ipc::circ::cc_t curr_conns; ipc::circ::cc_t conn_id; - } *r_info = ipc::mem::alloc(recycle_t{ + } *r_info = ipc::mem::$new(recycle_t{ buf_id, inf, que->elems()->connections(std::memory_order_relaxed), que->connected_id() }); if (r_info == nullptr) { - ipc::log("fail: ipc::mem::alloc.\n"); + ipc::log("fail: ipc::mem::$new.\n"); return ipc::buff_t{buf, msg_size}; // no recycle } else { return ipc::buff_t{buf, msg_size, [](void* p_info, std::size_t size) { auto r_info = static_cast(p_info); LIBIPC_UNUSED auto finally = ipc::guard([r_info] { - ipc::mem::free(r_info); + ipc::mem::$delete(r_info); }); recycle_storage(r_info->storage_id, r_info->inf, diff --git a/src/libipc/mem/resource.h b/src/libipc/mem/resource.h index b1f84c4..c864fe0 100755 --- a/src/libipc/mem/resource.h +++ b/src/libipc/mem/resource.h @@ -5,22 +5,10 @@ #include #include "libipc/def.h" -#include "libipc/memory/alloc.h" #include "libipc/imp/fmt.h" #include "libipc/mem/polymorphic_allocator.h" namespace ipc { -namespace mem { - -//using async_pool_alloc = static_wrapper, -// fixed_expand_policy -// >, -// default_recycler >>>; -using async_pool_alloc = ipc::mem::static_alloc; - -} // namespace mem template struct hash : public std::hash {}; diff --git a/src/libipc/memory/alloc.h b/src/libipc/memory/alloc.h deleted file mode 100755 index 29cbc2e..0000000 --- a/src/libipc/memory/alloc.h +++ /dev/null @@ -1,423 +0,0 @@ -#pragma once - -#include -#include -#include -#include // std::numeric_limits -#include -#include // assert - -#include "libipc/def.h" -#include "libipc/rw_lock.h" - -#include "libipc/utility/concept.h" -#include "libipc/platform/detail.h" - -namespace ipc { -namespace mem { - -class static_alloc { -public: - static void swap(static_alloc&) noexcept {} - - static void* alloc(std::size_t size) noexcept { - return size ? std::malloc(size) : nullptr; - } - - static void free(void* p) noexcept { - std::free(p); - } - - static void free(void* p, std::size_t /*size*/) noexcept { - free(p); - } -}; - -//////////////////////////////////////////////////////////////// -/// Scope allocation -- The destructor will release all allocated blocks. -//////////////////////////////////////////////////////////////// - -namespace detail { - -constexpr std::size_t aligned(std::size_t size, size_t alignment) noexcept { - return ( (size - 1) & ~(alignment - 1) ) + alignment; -} - -IPC_CONCEPT_(has_take, take(std::move(std::declval()))); - -class scope_alloc_base { -protected: - struct block_t { - std::size_t size_; - block_t * next_; - } * head_ = nullptr, * tail_ = nullptr; - - enum : std::size_t { - aligned_block_size = aligned(sizeof(block_t), alignof(std::max_align_t)) - }; - -public: - void swap(scope_alloc_base & rhs) { - std::swap(head_, rhs.head_); - std::swap(tail_, rhs.tail_); - } - - bool empty() const noexcept { - return head_ == nullptr; - } - - void take(scope_alloc_base && rhs) { - if (rhs.empty()) return; - if (empty()) swap(rhs); - else { - std::swap(tail_->next_, rhs.head_); - // rhs.head_ should be nullptr here - tail_ = rhs.tail_; - rhs.tail_ = nullptr; - } - } - - void free(void* /*p*/) {} - void free(void* /*p*/, std::size_t) {} -}; - -} // namespace detail - -template -class scope_alloc : public detail::scope_alloc_base { -public: - using base_t = detail::scope_alloc_base; - using alloc_policy = AllocP; - -private: - alloc_policy alloc_; - - void free_all() { - while (!empty()) { - auto curr = head_; - head_ = head_->next_; - alloc_.free(curr, curr->size_); - } - // now head_ is nullptr - } - -public: - scope_alloc() = default; - - scope_alloc(scope_alloc && rhs) { swap(rhs); } - scope_alloc& operator=(scope_alloc rhs) { swap(rhs); return (*this); } - - ~scope_alloc() { free_all(); } - - void swap(scope_alloc& rhs) { - alloc_.swap(rhs.alloc_); - base_t::swap(rhs); - } - - template - auto take(scope_alloc && rhs) -> ipc::require::value> { - base_t::take(std::move(rhs)); - alloc_.take(std::move(rhs.alloc_)); - } - - template - auto take(scope_alloc && rhs) -> ipc::require::value> { - base_t::take(std::move(rhs)); - } - - void* alloc(std::size_t size) { - std::size_t real_size = aligned_block_size + size; - auto curr = static_cast(alloc_.alloc(real_size)); - curr->size_ = real_size; - curr->next_ = head_; - head_ = curr; - if (tail_ == nullptr) { - tail_ = curr; - } - return (reinterpret_cast(curr) + aligned_block_size); - } -}; - -//////////////////////////////////////////////////////////////// -/// Fixed-size blocks allocation -//////////////////////////////////////////////////////////////// - -namespace detail { - -class fixed_alloc_base { -protected: - std::size_t block_size_; - std::size_t init_expand_; - void * cursor_; - - void init(std::size_t block_size, std::size_t init_expand) { - block_size_ = block_size; - init_expand_ = init_expand; - cursor_ = nullptr; - } - - static void** node_p(void* node) { - return reinterpret_cast(node); - } - - static auto& next(void* node) { - return *node_p(node); - } - -public: - bool operator<(fixed_alloc_base const & right) const { - return init_expand_ < right.init_expand_; - } - - void set_block_size(std::size_t block_size) { - block_size_ = block_size; - } - - void swap(fixed_alloc_base& rhs) { - std::swap(block_size_ , rhs.block_size_); - std::swap(init_expand_, rhs.init_expand_); - std::swap(cursor_ , rhs.cursor_); - } - - bool empty() const noexcept { - return cursor_ == nullptr; - } - - void take(fixed_alloc_base && rhs) { - assert(block_size_ == rhs.block_size_); - init_expand_ = (ipc::detail::max)(init_expand_, rhs.init_expand_); - if (rhs.empty()) return; - auto curr = cursor_; - if (curr != nullptr) while (1) { - auto next_cur = next(curr); - if (next_cur == nullptr) { - std::swap(next(curr), rhs.cursor_); - return; - } - // next_cur != nullptr - else curr = next_cur; - } - // curr == nullptr, means cursor_ == nullptr - else std::swap(cursor_, rhs.cursor_); - // rhs.cursor_ must be nullptr - } - - void free(void* p) { - if (p == nullptr) return; - next(p) = cursor_; - cursor_ = p; - } - - void free(void* p, std::size_t) { - free(p); - } -}; - -template -class fixed_alloc : public detail::fixed_alloc_base { -public: - using base_t = detail::fixed_alloc_base; - using alloc_policy = AllocP; - -private: - alloc_policy alloc_; - - void* try_expand() { - if (empty()) { - auto size = ExpandP::next(block_size_, init_expand_); - auto p = node_p(cursor_ = alloc_.alloc(size)); - for (std::size_t i = 0; i < (size / block_size_) - 1; ++i) - p = node_p((*p) = reinterpret_cast(p) + block_size_); - (*p) = nullptr; - } - return cursor_; - } - -public: - explicit fixed_alloc(std::size_t block_size, std::size_t init_expand = 1) { - init(block_size, init_expand); - } - - fixed_alloc(fixed_alloc && rhs) { - init(0, 0); - swap(rhs); - } - - fixed_alloc& operator=(fixed_alloc rhs) { - swap(rhs); - return (*this); - } - - void swap(fixed_alloc& rhs) { - alloc_.swap(rhs.alloc_); - base_t::swap(rhs); - } - - template - auto take(fixed_alloc && rhs) -> ipc::require::value> { - base_t::take(std::move(rhs)); - alloc_.take(std::move(rhs.alloc_)); - } - - void* alloc() { - void* p = try_expand(); - cursor_ = next(p); - return p; - } - - void* alloc(std::size_t) { - return alloc(); - } -}; - -} // namespace detail - -template ::max)()> -struct fixed_expand_policy { - - enum : std::size_t { - base_size = BaseSize, - limit_size = LimitSize - }; - - constexpr static std::size_t prev(std::size_t e) noexcept { - return ((e / 2) == 0) ? 1 : (e / 2); - } - - constexpr static std::size_t next(std::size_t e) noexcept { - return e * 2; - } - - static std::size_t next(std::size_t block_size, std::size_t & e) { - auto n = ipc::detail::max(block_size, base_size) * e; - e = ipc::detail::min(limit_size, next(e)); - return n; - } -}; - -template , - typename ExpandP = fixed_expand_policy<>> -class fixed_alloc : public detail::fixed_alloc { -public: - using base_t = detail::fixed_alloc; - - enum : std::size_t { - block_size = ipc::detail::max(BlockSize, sizeof(void*)) - }; - -public: - explicit fixed_alloc(std::size_t init_expand) - : base_t(block_size, init_expand) { - } - - fixed_alloc() : fixed_alloc(1) {} - - fixed_alloc(fixed_alloc && rhs) - : base_t(std::move(rhs)) { - } - - fixed_alloc& operator=(fixed_alloc rhs) { - swap(rhs); - return (*this); - } - - void swap(fixed_alloc& rhs) { - base_t::swap(rhs); - } -}; - -//////////////////////////////////////////////////////////////// -/// Variable-size blocks allocation (without alignment) -//////////////////////////////////////////////////////////////// - -namespace detail { - -class variable_alloc_base { -protected: - byte_t * head_ = nullptr, * tail_ = nullptr; - -public: - void swap(variable_alloc_base & rhs) { - std::swap(head_, rhs.head_); - std::swap(tail_, rhs.tail_); - } - - std::size_t remain() const noexcept { - return static_cast(tail_ - head_); - } - - bool empty() const noexcept { - return remain() == 0; - } - - void take(variable_alloc_base && rhs) { - if (remain() < rhs.remain()) { - // replace this by rhs - head_ = rhs.head_; - tail_ = rhs.tail_; - } - // discard rhs - rhs.head_ = rhs.tail_ = nullptr; - } - - void free(void* /*p*/) {} - void free(void* /*p*/, std::size_t) {} -}; - -} // namespace detail - -template > -class variable_alloc : public detail::variable_alloc_base { -public: - using base_t = detail::variable_alloc_base; - using alloc_policy = AllocP; - - enum : std::size_t { - aligned_chunk_size = detail::aligned(ChunkSize, alignof(std::max_align_t)) - }; - -private: - alloc_policy alloc_; - -public: - variable_alloc() = default; - - variable_alloc(variable_alloc && rhs) { swap(rhs); } - variable_alloc& operator=(variable_alloc rhs) { swap(rhs); return (*this); } - - void swap(variable_alloc& rhs) { - alloc_.swap(rhs.alloc_); - base_t::swap(rhs); - } - - template - auto take(variable_alloc && rhs) -> ipc::require::value> { - base_t::take(std::move(rhs)); - alloc_.take(std::move(rhs.alloc_)); - } - - void* alloc(std::size_t size) { - /* - * byte alignment is always alignof(std::max_align_t). - */ - size = detail::aligned(size, alignof(std::max_align_t)); - void* ptr; - // size would never be 0 here - if (remain() < size) { - std::size_t chunk_size = ipc::detail::max(aligned_chunk_size, size); - ptr = alloc_.alloc(chunk_size); - tail_ = static_cast(ptr) + chunk_size; - head_ = tail_ - (chunk_size - size); - } - else { - ptr = head_; - head_ += size; - } - return ptr; - } -}; - -} // namespace mem -} // namespace ipc diff --git a/src/libipc/memory/wrapper.h b/src/libipc/memory/wrapper.h deleted file mode 100755 index cf0b905..0000000 --- a/src/libipc/memory/wrapper.h +++ /dev/null @@ -1,327 +0,0 @@ -#pragma once - -#include -#include -#include // std::deque -#include // std::function -#include // std::forward -#include -#include // assert -#include // std::aligned_storage_t - -#include "libipc/def.h" -#include "libipc/rw_lock.h" -#include "libipc/pool_alloc.h" - -#include "libipc/utility/concept.h" -#include "libipc/memory/alloc.h" -#include "libipc/platform/detail.h" - -namespace ipc { -namespace mem { - -//////////////////////////////////////////////////////////////// -/// Thread-safe allocation wrapper -//////////////////////////////////////////////////////////////// - -namespace detail { - -IPC_CONCEPT_(is_comparable, operator<(std::declval())); - -} // namespace detail - -template ::value> -class limited_recycler; - -template -class limited_recycler { -public: - using alloc_policy = AllocP; - -protected: - std::deque master_allocs_; - ipc::spin_lock master_lock_; - - template - void take_first_do(F && pred) { - auto it = master_allocs_.begin(); - pred(const_cast(*it)); - master_allocs_.erase(it); - } - -public: - void try_recover(alloc_policy & alc) { - LIBIPC_UNUSED auto guard = ipc::detail::unique_lock(master_lock_); - if (master_allocs_.empty()) return; - take_first_do([&alc](alloc_policy & first) { alc.swap(first); }); - } - - void collect(alloc_policy && alc) { - LIBIPC_UNUSED auto guard = ipc::detail::unique_lock(master_lock_); - if (master_allocs_.size() >= 32) { - take_first_do([](alloc_policy &) {}); // erase first - } - master_allocs_.emplace_back(std::move(alc)); - } - - IPC_CONSTEXPR_ auto try_replenish(alloc_policy&, std::size_t) noexcept {} -}; - -template -class default_recycler : public limited_recycler { - - IPC_CONCEPT_(has_remain, remain()); - IPC_CONCEPT_(has_empty , empty()); - - template - void try_fill(A & alc) { - LIBIPC_UNUSED auto guard = ipc::detail::unique_lock(this->master_lock_); - if (this->master_allocs_.empty()) return; - this->take_first_do([&alc](alloc_policy & first) { alc.take(std::move(first)); }); - } - -public: - using alloc_policy = typename limited_recycler::alloc_policy; - - template - auto try_replenish(alloc_policy & alc, std::size_t size) - -> ipc::require::value && has_remain::value> { - if (alc.remain() >= size) return; - this->try_fill(alc); - } - - template - auto try_replenish(alloc_policy & alc, std::size_t /*size*/) - -> ipc::require::value && !has_remain::value && has_empty::value> { - if (!alc.empty()) return; - this->try_fill(alc); - } - - template - auto try_replenish(alloc_policy & alc, std::size_t /*size*/) - -> ipc::require::value && has_empty::value> { - if (!alc.empty()) return; - this->try_recover(alc); - } - - template - IPC_CONSTEXPR_ auto try_replenish(alloc_policy & /*alc*/, std::size_t /*size*/) noexcept - -> ipc::require<(!detail::has_take::value || !has_remain::value) && !has_empty::value> { - // Do Nothing. - } -}; - -template -class empty_recycler { -public: - using alloc_policy = AllocP; - - IPC_CONSTEXPR_ void try_recover(alloc_policy&) noexcept {} - IPC_CONSTEXPR_ auto try_replenish(alloc_policy&, std::size_t) noexcept {} - IPC_CONSTEXPR_ void collect(alloc_policy&&) noexcept {} -}; - -template class RecyclerP = default_recycler> -class async_wrapper { -public: - using alloc_policy = AllocP; - -private: - RecyclerP recycler_; - - class alloc_proxy : public AllocP { - async_wrapper * w_ = nullptr; - - public: - alloc_proxy(alloc_proxy && rhs) = default; - - template - alloc_proxy(async_wrapper* w, P && ... pars) - : AllocP(std::forward

(pars) ...), w_(w) { - assert(w_ != nullptr); - w_->recycler_.try_recover(*this); - } - - ~alloc_proxy() { - w_->recycler_.collect(std::move(*this)); - } - - auto alloc(std::size_t size) { - w_->recycler_.try_replenish(*this, size); - return AllocP::alloc(size); - } - }; - - friend class alloc_proxy; - using ref_t = alloc_proxy&; - - std::function get_alloc_; - -public: - template - async_wrapper(P ... pars) { - get_alloc_ = [this, pars ...]()->ref_t { - thread_local alloc_proxy tls(pars ...); - return tls; - }; - } - - void* alloc(std::size_t size) { - return get_alloc_().alloc(size); - } - - void free(void* p, std::size_t size) { - get_alloc_().free(p, size); - } -}; - -//////////////////////////////////////////////////////////////// -/// Thread-safe allocation wrapper (with spin_lock) -//////////////////////////////////////////////////////////////// - -template -class sync_wrapper { -public: - using alloc_policy = AllocP; - using mutex_type = MutexT; - -private: - mutex_type lock_; - alloc_policy alloc_; - -public: - template - sync_wrapper(P && ... pars) - : alloc_(std::forward

(pars) ...) - {} - - void swap(sync_wrapper& rhs) { - LIBIPC_UNUSED auto guard = ipc::detail::unique_lock(lock_); - alloc_.swap(rhs.alloc_); - } - - void* alloc(std::size_t size) { - LIBIPC_UNUSED auto guard = ipc::detail::unique_lock(lock_); - return alloc_.alloc(size); - } - - void free(void* p, std::size_t size) { - LIBIPC_UNUSED auto guard = ipc::detail::unique_lock(lock_); - alloc_.free(p, size); - } -}; - -//////////////////////////////////////////////////////////////// -/// Variable memory allocation wrapper -//////////////////////////////////////////////////////////////// - -template -struct default_mapping_policy { - - enum : std::size_t { - base_size = BaseSize, - iter_size = IterSize, - classes_size = 64 - }; - - template - IPC_CONSTEXPR_ static void foreach(F && f, P && ... params) { - for (std::size_t i = 0; i < classes_size; ++i) { - f(i, std::forward

(params)...); - } - } - - IPC_CONSTEXPR_ static std::size_t block_size(std::size_t id) noexcept { - return (id < classes_size) ? (base_size + (id + 1) * iter_size) : 0; - } - - template - IPC_CONSTEXPR_ static auto classify(F && f, D && d, std::size_t size, P && ... params) { - std::size_t id = (size - base_size - 1) / iter_size; - return (id < classes_size) ? - f(id, size, std::forward

(params)...) : - d(size, std::forward

(params)...); - } -}; - -template > -class variable_wrapper { - - struct initiator { - - using falc_t = std::aligned_storage_t; - falc_t arr_[MappingP::classes_size]; - - initiator() { - MappingP::foreach([](std::size_t id, falc_t * a) { - ipc::mem::construct(&initiator::at(a, id), MappingP::block_size(id)); - }, arr_); - } - - ~initiator() { - MappingP::foreach([](std::size_t id, falc_t * a) { - ipc::mem::destruct(&initiator::at(a, id)); - }, arr_); - } - - static FixedAlloc & at(falc_t * arr, std::size_t id) noexcept { - return reinterpret_cast(arr[id]); - } - } init_; - - using falc_t = typename initiator::falc_t; - -public: - void swap(variable_wrapper & other) { - MappingP::foreach([](std::size_t id, falc_t * in, falc_t * ot) { - initiator::at(in, id).swap(initiator::at(ot, id)); - }, init_.arr_, other.init_.arr_); - } - - void* alloc(std::size_t size) { - return MappingP::classify([](std::size_t id, std::size_t size, falc_t * a) { - return initiator::at(a, id).alloc(size); - }, [](std::size_t size, falc_t *) { - return DefaultAlloc::alloc(size); - }, size, init_.arr_); - } - - void free(void* p, std::size_t size) { - MappingP::classify([](std::size_t id, std::size_t size, void* p, falc_t * a) { - initiator::at(a, id).free(p, size); - }, [](std::size_t size, void* p, falc_t *) { - DefaultAlloc::free(p, size); - }, size, p, init_.arr_); - } -}; - -//////////////////////////////////////////////////////////////// -/// Static allocation wrapper -//////////////////////////////////////////////////////////////// - -template -class static_wrapper { -public: - using alloc_policy = AllocP; - - static alloc_policy& instance() { - static alloc_policy alloc; - return alloc; - } - - static void swap(static_wrapper&) {} - - static void* alloc(std::size_t size) { - return instance().alloc(size); - } - - static void free(void* p, std::size_t size) { - instance().free(p, size); - } -}; - -} // namespace mem -} // namespace ipc diff --git a/src/libipc/platform/posix/shm_posix.cpp b/src/libipc/platform/posix/shm_posix.cpp index 7221d05..65eb5db 100644 --- a/src/libipc/platform/posix/shm_posix.cpp +++ b/src/libipc/platform/posix/shm_posix.cpp @@ -13,10 +13,10 @@ #include "libipc/shm.h" #include "libipc/def.h" -#include "libipc/pool_alloc.h" #include "libipc/utility/log.h" #include "libipc/mem/resource.h" +#include "libipc/mem/new.h" namespace { @@ -81,7 +81,7 @@ id_t acquire(char const * name, std::size_t size, unsigned mode) { ::fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - auto ii = mem::alloc(); + auto ii = mem::$new(); ii->fd_ = fd; ii->size_ = size; ii->name_ = std::move(op_name); @@ -177,7 +177,7 @@ std::int32_t release(id_t id) noexcept { } } else ::munmap(ii->mem_, ii->size_); - mem::free(ii); + mem::$delete(ii); return ret; } diff --git a/src/libipc/platform/win/shm_win.cpp b/src/libipc/platform/win/shm_win.cpp index 7942a62..c082dac 100755 --- a/src/libipc/platform/win/shm_win.cpp +++ b/src/libipc/platform/win/shm_win.cpp @@ -6,10 +6,10 @@ #include "libipc/shm.h" #include "libipc/def.h" -#include "libipc/pool_alloc.h" #include "libipc/utility/log.h" #include "libipc/mem/resource.h" +#include "libipc/mem/new.h" #include "to_tchar.h" #include "get_sa.h" @@ -58,7 +58,7 @@ id_t acquire(char const * name, std::size_t size, unsigned mode) { return nullptr; } } - auto ii = mem::alloc(); + auto ii = mem::$new(); ii->h_ = h; ii->size_ = size; return ii; @@ -116,7 +116,7 @@ std::int32_t release(id_t id) noexcept { ipc::error("fail release: invalid id (h = null)\n"); } else ::CloseHandle(ii->h_); - mem::free(ii); + mem::$delete(ii); return 0; } diff --git a/src/libipc/pool_alloc.cpp b/src/libipc/pool_alloc.cpp deleted file mode 100755 index b84e73b..0000000 --- a/src/libipc/pool_alloc.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "libipc/pool_alloc.h" - -#include "libipc/mem/resource.h" - -namespace ipc { -namespace mem { - -void* pool_alloc::alloc(std::size_t size) noexcept { - return async_pool_alloc::alloc(size); -} - -void pool_alloc::free(void* p, std::size_t size) noexcept { - async_pool_alloc::free(p, size); -} - -} // namespace mem -} // namespace ipc diff --git a/src/libipc/utility/pimpl.h b/src/libipc/utility/pimpl.h index ca0edd3..7151045 100755 --- a/src/libipc/utility/pimpl.h +++ b/src/libipc/utility/pimpl.h @@ -5,7 +5,7 @@ #include "libipc/platform/detail.h" #include "libipc/utility/concept.h" -#include "libipc/pool_alloc.h" +#include "libipc/mem/new.h" namespace ipc { @@ -36,12 +36,12 @@ IPC_CONSTEXPR_ auto clear_impl(T* p) -> IsImplComfortable { template IPC_CONSTEXPR_ auto make_impl(P&&... params) -> IsImplUncomfortable { - return mem::alloc(std::forward

(params)...); + return mem::$new(std::forward

(params)...); } template IPC_CONSTEXPR_ auto clear_impl(T* p) -> IsImplUncomfortable { - mem::free(p); + mem::$delete(p); } template diff --git a/test/mem/test_mem_allocator.cpp b/test/mem/test_mem_allocator.cpp index 1103c9c..5702a07 100644 --- a/test/mem/test_mem_allocator.cpp +++ b/test/mem/test_mem_allocator.cpp @@ -11,12 +11,12 @@ #include "libipc/mem/polymorphic_allocator.h" #include "libipc/mem/memory_resource.h" -TEST(polymorphic_allocator, construct) { +TEST(polymorphic_allocator, ctor) { ipc::mem::bytes_allocator alc; SUCCEED(); } -TEST(polymorphic_allocator, construct_value_initialization) { +TEST(polymorphic_allocator, ctor_value_initialization) { ipc::mem::bytes_allocator alc{}; auto p = alc.allocate(128); EXPECT_NE(p, nullptr); @@ -57,7 +57,7 @@ TEST(polymorphic_allocator, memory_resource_traits) { #endif } -TEST(polymorphic_allocator, construct_copy_move) { +TEST(polymorphic_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}; diff --git a/test/mem/test_mem_central_cache_pool.cpp b/test/mem/test_mem_central_cache_pool.cpp index e6cf19b..4e1ff5a 100644 --- a/test/mem/test_mem_central_cache_pool.cpp +++ b/test/mem/test_mem_central_cache_pool.cpp @@ -12,16 +12,16 @@ TEST(central_cache_pool, ctor) { ASSERT_FALSE((std::is_copy_assignable, 1>>::value)); ASSERT_FALSE((std::is_move_assignable, 1>>::value)); { - auto &pool = ipc::mem::central_cache_pool, 1>::instance(); - ipc::mem::block<1> *b1 = pool.aqueire(); + auto &pool = ipc::mem::central_cache_pool, 1>::instance(); + ipc::mem::block<1024> *b1 = pool.aqueire(); ASSERT_FALSE(nullptr == b1); - ASSERT_TRUE (nullptr == b1->next); + EXPECT_TRUE (nullptr == b1->next); pool.release(b1); - ipc::mem::block<1> *b2 = pool.aqueire(); + ipc::mem::block<1024> *b2 = pool.aqueire(); EXPECT_EQ(b1, b2); - ipc::mem::block<1> *b3 = pool.aqueire(); + ipc::mem::block<1024> *b3 = pool.aqueire(); ASSERT_FALSE(nullptr == b3); - ASSERT_TRUE (nullptr == b3->next); + EXPECT_TRUE (nullptr == b3->next); EXPECT_NE(b1, b3); } { @@ -29,7 +29,7 @@ TEST(central_cache_pool, ctor) { ipc::mem::block<1> *b1 = pool.aqueire(); ASSERT_FALSE(nullptr == b1); ASSERT_FALSE(nullptr == b1->next); - ASSERT_TRUE (nullptr == b1->next->next); + EXPECT_TRUE (nullptr == b1->next->next); pool.release(b1); ipc::mem::block<1> *b2 = pool.aqueire(); EXPECT_EQ(b1, b2); @@ -38,7 +38,7 @@ TEST(central_cache_pool, ctor) { ipc::mem::block<1> *b4 = pool.aqueire(); ASSERT_FALSE(nullptr == b4); ASSERT_FALSE(nullptr == b4->next); - ASSERT_TRUE (nullptr == b4->next->next); + EXPECT_TRUE (nullptr == b4->next->next); EXPECT_NE(b1, b4); } } diff --git a/test/test_ipc.cpp b/test/test_ipc.cpp index a482fcb..00dcd27 100755 --- a/test/test_ipc.cpp +++ b/test/test_ipc.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "libipc/ipc.h" #include "libipc/buffer.h" @@ -84,18 +85,19 @@ void test_basic(char const * name) { } class data_set { - std::vector datas_; + alignas(rand_buf) char datas_[sizeof(rand_buf[LoopCount])]; + rand_buf *d_; public: data_set() { - datas_.resize(LoopCount); + d_ = ::new(datas_) rand_buf[LoopCount]; for (int i = 0; i < LoopCount; ++i) { - datas_[i].set_id(i); + d_[i].set_id(i); } } - std::vector const &get() const noexcept { - return datas_; + rand_buf const *get() const noexcept { + return d_; } } const data_set__; @@ -112,7 +114,7 @@ void test_sr(char const * name, int s_cnt, int r_cnt) { Que que { name, ipc::sender }; ASSERT_TRUE(que.wait_for_recv(r_cnt)); sw.start(); - for (int i = 0; i < (int)data_set__.get().size(); ++i) { + for (int i = 0; i < LoopCount; ++i) { ASSERT_TRUE(que.send(data_set__.get()[i])); } }; @@ -128,7 +130,7 @@ void test_sr(char const * name, int s_cnt, int r_cnt) { if (i == -1) { return; } - ASSERT_TRUE((i >= 0) && (i < (int)data_set__.get().size())); + ASSERT_TRUE((i >= 0) && (i < LoopCount)); auto const &data_set = data_set__.get()[i]; if (data_set != got) { printf("data_set__.get()[%d] != got, size = %zd/%zd\n", @@ -146,7 +148,7 @@ void test_sr(char const * name, int s_cnt, int r_cnt) { que.send(rand_buf{msg_head{-1}}); } ipc_ut::reader().wait_for_done(); - sw.print_elapsed(s_cnt, r_cnt, (int)data_set__.get().size(), name); + sw.print_elapsed(s_cnt, r_cnt, LoopCount, name); } } // internal-linkage