diff --git a/build/ipc.pro b/build/ipc.pro index a446988..652f270 100644 --- a/build/ipc.pro +++ b/build/ipc.pro @@ -24,6 +24,7 @@ HEADERS += \ ../include/def.h \ ../include/rw_lock.h \ ../include/tls_pointer.h \ + ../include/pool_alloc.h \ ../src/channel.inc \ ../src/route.inc \ ../src/id_pool.inc \ @@ -33,7 +34,8 @@ HEADERS += \ SOURCES += \ ../src/shm.cpp \ - ../src/ipc.cpp + ../src/ipc.cpp \ + ../src/pool_alloc.cpp unix { diff --git a/include/pool_alloc.h b/include/pool_alloc.h new file mode 100644 index 0000000..8747e08 --- /dev/null +++ b/include/pool_alloc.h @@ -0,0 +1,17 @@ +#pragma once + +#include "export.h" +#include "def.h" + +namespace ipc { +namespace mem { + +class IPC_EXPORT pool_alloc { +public: + static void clear(); + static void* alloc(std::size_t size); + static void free(void* p, std::size_t size); +}; + +} // namespace mem +} // namespace ipc diff --git a/src/memory/resource.hpp b/src/memory/resource.hpp index 3de049b..7469da0 100644 --- a/src/memory/resource.hpp +++ b/src/memory/resource.hpp @@ -26,46 +26,34 @@ constexpr decltype(auto) static_switch(std::size_t i, std::index_sequence{}, f, def); } -} // namespace detail +template +auto& fixed() { + static synchronized> pool; + return pool; +} + +template +decltype(auto) choose(std::size_t size, F&& f) { + enum : std::size_t { base_size = sizeof(void*) }; + size = ((size - 1) & (~(base_size - 1))) + base_size; + return detail::static_switch(size, std::index_sequence< + base_size , base_size * 2 , + base_size * 3 , base_size * 4 , + base_size * 5 , base_size * 6 , + base_size * 7 , base_size * 8 , + base_size * 9 , base_size * 10, + base_size * 11, base_size * 12, + base_size * 13, base_size * 14, + base_size * 15, base_size * 16 + >{}, [&f](auto index) { + return f(fixed()); + }, [&f] { return f(static_alloc{}); }); +} class pool_alloc { -private: - template - static auto& fixed() { - static synchronized> pool; - return pool; - } - - template - static decltype(auto) choose(std::size_t size, F&& f) { - enum : std::size_t { base_size = sizeof(void*) }; - size = ((size - 1) & (~(base_size - 1))) + base_size; - return detail::static_switch(size, std::index_sequence< - base_size , base_size * 2 , - base_size * 3 , base_size * 4 , - base_size * 5 , base_size * 6 , - base_size * 7 , base_size * 8 , - base_size * 9 , base_size * 10, - base_size * 11, base_size * 12, - base_size * 13, base_size * 14, - base_size * 15, base_size * 16 - >{}, [&f](auto index) { - return f(fixed()); - }, [&f] { return f(static_alloc{}); }); - } - public: - pool_alloc() = default; - pool_alloc(const pool_alloc&) = default; - pool_alloc& operator=(const pool_alloc&) = default; - pool_alloc(pool_alloc&&) = default; - pool_alloc& operator=(pool_alloc&&) = default; - - static constexpr std::size_t remain() { - return (std::numeric_limits::max)(); - } - static constexpr void clear() {} + static constexpr void swap(pool_alloc&) {} static void* alloc(std::size_t size) { return choose(size, [size](auto&& fp) { return fp.alloc(size); }); @@ -76,8 +64,10 @@ public: } }; +} // namespace detail + template -using allocator = allocator_wrapper; +using allocator = allocator_wrapper; template using unordered_map = std::unordered_map< diff --git a/src/pool_alloc.cpp b/src/pool_alloc.cpp new file mode 100644 index 0000000..64d7e73 --- /dev/null +++ b/src/pool_alloc.cpp @@ -0,0 +1,21 @@ +#include "pool_alloc.h" + +#include "memory/resource.hpp" + +namespace ipc { +namespace mem { + +void pool_alloc::clear() { + detail::pool_alloc::clear(); +} + +void* pool_alloc::alloc(std::size_t size) { + return detail::pool_alloc::alloc(size); +} + +void pool_alloc::free(void* p, std::size_t size) { + detail::pool_alloc::free(p, size); +} + +} // namespace mem +} // namespace ipc diff --git a/test/test.h b/test/test.h index ff71177..1b57330 100644 --- a/test/test.h +++ b/test/test.h @@ -115,7 +115,7 @@ void benchmark_prod_cons(T* cq) { // std::cout << cid << "-consumer-disconnect" << std::endl; // } tcq.disconnect(cn); - if (++fini_c != std::extent::value) { + if ((fini_c.fetch_add(1, std::memory_order_relaxed) + 1) != std::extent::value) { // std::unique_lock guard { lc }; // std::cout << cid << "-consumer-end" << std::endl; return; @@ -141,7 +141,9 @@ void benchmark_prod_cons(T* cq) { // } tcq.send(cn, { pid, i }); } - if (++fini_p != std::extent::value) return; + if ((fini_p.fetch_add(1, std::memory_order_relaxed) + 1) != std::extent::value) { + return; + } // quit tcq.send(cn, { -1, -1 }); }}; diff --git a/test/test_ipc.cpp b/test/test_ipc.cpp index 21c27c6..9c18e62 100644 --- a/test/test_ipc.cpp +++ b/test/test_ipc.cpp @@ -258,7 +258,7 @@ void benchmark_lc() { } std::this_thread::yield(); } - if (++fini == std::extent::value) { + if ((fini.fetch_add(1, std::memory_order_relaxed) + 1) == std::extent::value) { sw.print_elapsed(W, R, Loops); } std::uint64_t sum = 0; diff --git a/test/test_mem.cpp b/test/test_mem.cpp index 5625b34..e52dee2 100644 --- a/test/test_mem.cpp +++ b/test/test_mem.cpp @@ -6,6 +6,8 @@ #include "random.hpp" #include "memory/resource.hpp" +#include "pool_alloc.h" + #include "test.h" namespace { @@ -21,7 +23,8 @@ private slots: void initTestCase(); void cleanupTestCase(); - void test_alloc(); + void test_alloc_free(); + void test_linear(); } unit__; #include "test_mem.moc" @@ -91,6 +94,27 @@ void Unit::cleanupTestCase() { sizes__.clear(); } +template +void benchmark_alloc() { + std::cout << std::endl << type_name() << std::endl; + + test_stopwatch sw; + sw.start(); + + for (std::size_t x = 0; x < 10; ++x) + for (std::size_t n = 0; n < LoopCount; ++n) { + std::size_t s = sizes__[n]; + AllocT::free(AllocT::alloc(s), s); + } + + sw.print_elapsed<1>(DataMin, DataMax, LoopCount * 10); +} + +void Unit::test_alloc_free() { + benchmark_alloc(); + benchmark_alloc(); +} + template void benchmark_alloc() { std::cout << std::endl @@ -126,7 +150,7 @@ void benchmark_alloc() { } } } - if (++fini == ThreadsN) { + if ((fini.fetch_add(1, std::memory_order_relaxed) + 1) == ThreadsN) { sw.print_elapsed<1>(DataMin, DataMax, LoopCount); } }}; @@ -152,7 +176,7 @@ struct test_performance { } }; -void Unit::test_alloc() { +void Unit::test_linear() { // malloc test_performance::start(); test_performance::start();