diff --git a/include/util/pool_allocator.hpp b/include/util/pool_allocator.hpp index 94e045e3d..f082b7782 100644 --- a/include/util/pool_allocator.hpp +++ b/include/util/pool_allocator.hpp @@ -13,19 +13,18 @@ namespace osrm::util { #if 1 -template class PoolAllocator +template +class PoolAllocator; + +template +class MemoryManager { - public: - using value_type = T; - - PoolAllocator() noexcept = default; - - template PoolAllocator(const PoolAllocator &) noexcept {} - - template struct rebind +public: + static MemoryManager &instance() { - using other = PoolAllocator; - }; + thread_local MemoryManager instance; + return instance; + } T *allocate(std::size_t n) { @@ -55,7 +54,7 @@ template class PoolAllocator free_lists_[free_list_index].push_back(p); } - ~PoolAllocator() + ~MemoryManager() { for (auto block : blocks_) { @@ -63,44 +62,11 @@ template class PoolAllocator } } - PoolAllocator(const PoolAllocator &) = delete; - PoolAllocator &operator=(const PoolAllocator &) = delete; - - PoolAllocator(PoolAllocator &&other) noexcept - : free_lists_(std::move(other.free_lists_)), - blocks_(std::move(other.blocks_)), - current_block_ptr_(other.current_block_ptr_), - current_block_left_items_(other.current_block_left_items_), - total_allocated_(other.total_allocated_) - { - other.current_block_ptr_ = nullptr; - other.current_block_left_items_ = 0; - other.total_allocated_ = 0; - } - - PoolAllocator &operator=(PoolAllocator &&other) noexcept - { - if (this != &other) - { - for (auto block : blocks_) - { - std::free(block); - } - - free_lists_ = std::move(other.free_lists_); - blocks_ = std::move(other.blocks_); - current_block_ptr_ = other.current_block_ptr_; - current_block_left_items_ = other.current_block_left_items_; - total_allocated_ = other.total_allocated_; - - other.current_block_ptr_ = nullptr; - other.current_block_left_items_ = 0; - other.total_allocated_ = 0; - } - return *this; - } - private: + MemoryManager() = default; + MemoryManager(const MemoryManager &) = delete; + MemoryManager &operator=(const MemoryManager &) = delete; + size_t get_next_power_of_two_exponent(size_t n) const { BOOST_ASSERT(n > 0); @@ -110,7 +76,7 @@ private: void allocate_block(size_t items_in_block) { items_in_block = std::max(items_in_block, MinItemsInBlock); - + size_t block_size = items_in_block * sizeof(T); T *block = static_cast(std::malloc(block_size)); if (!block) @@ -131,6 +97,48 @@ private: size_t total_allocated_ = 0; }; +template +class PoolAllocator +{ +public: + using value_type = T; + + PoolAllocator() noexcept = default; + + template + PoolAllocator(const PoolAllocator &) noexcept {} + + template + struct rebind + { + using other = PoolAllocator; + }; + + T *allocate(std::size_t n) + { + return MemoryManager::instance().allocate(n); + } + + void deallocate(T *p, std::size_t n) noexcept + { + MemoryManager::instance().deallocate(p, n); + } + + ~PoolAllocator() = default; + + PoolAllocator(const PoolAllocator &) = default; + PoolAllocator &operator=(const PoolAllocator &) = default; + PoolAllocator(PoolAllocator &&) noexcept = default; + PoolAllocator &operator=(PoolAllocator &&) noexcept = default; + +private: + static size_t get_next_power_of_two_exponent(size_t n) + { + BOOST_ASSERT(n > 0); + return (sizeof(size_t) * 8) - std::countl_zero(n - 1); + } +}; + template bool operator==(const PoolAllocator &, const PoolAllocator &) { diff --git a/unit_tests/util/pool_allocator.cpp b/unit_tests/util/pool_allocator.cpp index 2d86161d0..21cff54a3 100644 --- a/unit_tests/util/pool_allocator.cpp +++ b/unit_tests/util/pool_allocator.cpp @@ -57,6 +57,21 @@ BOOST_AUTO_TEST_CASE(copy) pool2.deallocate(ptr, 1); } +BOOST_AUTO_TEST_CASE(move) +{ + PoolAllocator pool; + auto ptr = pool.allocate(1); + *ptr = 42; + BOOST_CHECK_NE(ptr, nullptr); + pool.deallocate(ptr, 1); + + PoolAllocator pool2(std::move(pool)); + ptr = pool2.allocate(1); + *ptr = 42; + BOOST_CHECK_NE(ptr, nullptr); + pool2.deallocate(ptr, 1); +} + BOOST_AUTO_TEST_CASE(unordered_map) { std::unordered_map, std::equal_to, PoolAllocator>> map;