#include #include #include #include "benchmark/benchmark.h" #include "libpmr/new.h" namespace { template class cache { public: template void push(U &&u) noexcept { data_[idx_++] = std::forward(u); } T &pop() noexcept { return data_[--idx_]; } bool at_begin() const noexcept { return idx_ == 0; } bool at_end() const noexcept { return idx_ == N; } private: std::array data_{}; std::size_t idx_{}; }; template class test_suit { void next(std::size_t &idx) noexcept { idx = (idx + 1) % 3; } public: ~test_suit() noexcept { for (auto &pts : pts_) { while (!pts.at_begin()) { P::deallocate(pts.pop()); } } } bool test_allocate() noexcept { auto &pts = pts_[idx_a_]; pts.push(P::allocate()); if (pts.at_end()) { next(idx_a_); idx_d_ = idx_a_; } return ++allocated_ < CacheSize; } bool test_deallocate() noexcept { auto &pts = pts_[idx_d_]; if (pts.at_begin()) { next(idx_d_); if (allocated_ == CacheSize) { allocated_ = CacheSize / 2; return true; } return allocated_ > 0; } P::deallocate(pts.pop()); --allocated_; return true; } private: cache pts_[3]; std::size_t idx_a_{}; std::size_t idx_d_{}; std::size_t allocated_{}; }; template struct policy_malloc { static void *allocate() noexcept { return std::malloc(AllocSize); } static void deallocate(void *p) noexcept { std::free(p); } }; template struct policy_cpp_new { static void *allocate() noexcept { return new char[AllocSize]; } static void deallocate(void *p) noexcept { delete[] static_cast(p); } }; template struct policy_pmr_new { static void *allocate() noexcept { return pmr::new$>(); } static void deallocate(void *p) noexcept { pmr::delete$(static_cast *>(p)); } }; template