Skip to content

Commit 6f04aa9

Browse files
wip
1 parent 1037256 commit 6f04aa9

File tree

2 files changed

+73
-50
lines changed

2 files changed

+73
-50
lines changed

include/util/pool_allocator.hpp

Lines changed: 58 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,18 @@ namespace osrm::util
1313
{
1414

1515
#if 1
16-
template <typename T, size_t MinItemsInBlock = 1024> class PoolAllocator
17-
{
18-
public:
19-
using value_type = T;
20-
21-
PoolAllocator() noexcept = default;
16+
template <typename T, size_t MinItemsInBlock = 1024>
17+
class PoolAllocator;
2218

23-
template <typename U> PoolAllocator(const PoolAllocator<U> &) noexcept {}
24-
25-
template <typename U> struct rebind
19+
template <typename T, size_t MinItemsInBlock = 1024>
20+
class MemoryManager
21+
{
22+
public:
23+
static MemoryManager &instance()
2624
{
27-
using other = PoolAllocator<U, MinItemsInBlock>;
28-
};
25+
thread_local MemoryManager instance;
26+
return instance;
27+
}
2928

3029
T *allocate(std::size_t n)
3130
{
@@ -55,52 +54,19 @@ template <typename T, size_t MinItemsInBlock = 1024> class PoolAllocator
5554
free_lists_[free_list_index].push_back(p);
5655
}
5756

58-
~PoolAllocator()
57+
~MemoryManager()
5958
{
6059
for (auto block : blocks_)
6160
{
6261
std::free(block);
6362
}
6463
}
6564

66-
PoolAllocator(const PoolAllocator &) = delete;
67-
PoolAllocator &operator=(const PoolAllocator &) = delete;
68-
69-
PoolAllocator(PoolAllocator &&other) noexcept
70-
: free_lists_(std::move(other.free_lists_)),
71-
blocks_(std::move(other.blocks_)),
72-
current_block_ptr_(other.current_block_ptr_),
73-
current_block_left_items_(other.current_block_left_items_),
74-
total_allocated_(other.total_allocated_)
75-
{
76-
other.current_block_ptr_ = nullptr;
77-
other.current_block_left_items_ = 0;
78-
other.total_allocated_ = 0;
79-
}
80-
81-
PoolAllocator &operator=(PoolAllocator &&other) noexcept
82-
{
83-
if (this != &other)
84-
{
85-
for (auto block : blocks_)
86-
{
87-
std::free(block);
88-
}
89-
90-
free_lists_ = std::move(other.free_lists_);
91-
blocks_ = std::move(other.blocks_);
92-
current_block_ptr_ = other.current_block_ptr_;
93-
current_block_left_items_ = other.current_block_left_items_;
94-
total_allocated_ = other.total_allocated_;
95-
96-
other.current_block_ptr_ = nullptr;
97-
other.current_block_left_items_ = 0;
98-
other.total_allocated_ = 0;
99-
}
100-
return *this;
101-
}
102-
10365
private:
66+
MemoryManager() = default;
67+
MemoryManager(const MemoryManager &) = delete;
68+
MemoryManager &operator=(const MemoryManager &) = delete;
69+
10470
size_t get_next_power_of_two_exponent(size_t n) const
10571
{
10672
BOOST_ASSERT(n > 0);
@@ -110,7 +76,7 @@ template <typename T, size_t MinItemsInBlock = 1024> class PoolAllocator
11076
void allocate_block(size_t items_in_block)
11177
{
11278
items_in_block = std::max(items_in_block, MinItemsInBlock);
113-
79+
11480
size_t block_size = items_in_block * sizeof(T);
11581
T *block = static_cast<T *>(std::malloc(block_size));
11682
if (!block)
@@ -131,6 +97,48 @@ template <typename T, size_t MinItemsInBlock = 1024> class PoolAllocator
13197
size_t total_allocated_ = 0;
13298
};
13399

100+
template <typename T, size_t MinItemsInBlock>
101+
class PoolAllocator
102+
{
103+
public:
104+
using value_type = T;
105+
106+
PoolAllocator() noexcept = default;
107+
108+
template <typename U>
109+
PoolAllocator(const PoolAllocator<U> &) noexcept {}
110+
111+
template <typename U>
112+
struct rebind
113+
{
114+
using other = PoolAllocator<U, MinItemsInBlock>;
115+
};
116+
117+
T *allocate(std::size_t n)
118+
{
119+
return MemoryManager<T, MinItemsInBlock>::instance().allocate(n);
120+
}
121+
122+
void deallocate(T *p, std::size_t n) noexcept
123+
{
124+
MemoryManager<T, MinItemsInBlock>::instance().deallocate(p, n);
125+
}
126+
127+
~PoolAllocator() = default;
128+
129+
PoolAllocator(const PoolAllocator &) = default;
130+
PoolAllocator &operator=(const PoolAllocator &) = default;
131+
PoolAllocator(PoolAllocator &&) noexcept = default;
132+
PoolAllocator &operator=(PoolAllocator &&) noexcept = default;
133+
134+
private:
135+
static size_t get_next_power_of_two_exponent(size_t n)
136+
{
137+
BOOST_ASSERT(n > 0);
138+
return (sizeof(size_t) * 8) - std::countl_zero(n - 1);
139+
}
140+
};
141+
134142
template <typename T, typename U>
135143
bool operator==(const PoolAllocator<T> &, const PoolAllocator<U> &)
136144
{

unit_tests/util/pool_allocator.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,21 @@ BOOST_AUTO_TEST_CASE(copy)
5757
pool2.deallocate(ptr, 1);
5858
}
5959

60+
BOOST_AUTO_TEST_CASE(move)
61+
{
62+
PoolAllocator<int> pool;
63+
auto ptr = pool.allocate(1);
64+
*ptr = 42;
65+
BOOST_CHECK_NE(ptr, nullptr);
66+
pool.deallocate(ptr, 1);
67+
68+
PoolAllocator<int> pool2(std::move(pool));
69+
ptr = pool2.allocate(1);
70+
*ptr = 42;
71+
BOOST_CHECK_NE(ptr, nullptr);
72+
pool2.deallocate(ptr, 1);
73+
}
74+
6075
BOOST_AUTO_TEST_CASE(unordered_map)
6176
{
6277
std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, PoolAllocator<std::pair<const int, int>>> map;

0 commit comments

Comments
 (0)