Skip to content

Commit c578698

Browse files
wip
1 parent 8df282b commit c578698

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

include/util/pool_allocator.hpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#pragma once
2+
3+
#include <algorithm>
4+
#include <array>
5+
#include <bit>
6+
#include <boost/assert.hpp>
7+
#include <cstdlib>
8+
#include <iostream>
9+
#include <new>
10+
#include <vector>
11+
12+
namespace osrm::util
13+
{
14+
15+
template <typename T> class PoolAllocator
16+
{
17+
public:
18+
using value_type = T;
19+
20+
T *allocate(std::size_t n)
21+
{
22+
size_t free_list_index = get_next_power_of_two_exponent(n);
23+
auto &free_list = free_lists_[free_list_index];
24+
const auto items_in_block = 1u << free_list_index;
25+
if (free_list.empty())
26+
{
27+
// Check if there is space in current block
28+
if (current_block_left_items_ < items_in_block)
29+
{
30+
allocate_block(items_in_block);
31+
}
32+
33+
free_list.push_back(current_block_ptr_);
34+
current_block_left_items_ -= items_in_block;
35+
current_block_ptr_ += items_in_block;
36+
}
37+
auto ptr = free_list.back();
38+
free_list.pop_back();
39+
return ptr;
40+
}
41+
42+
void deallocate(T *p, std::size_t n) noexcept
43+
{
44+
size_t free_list_index = get_next_power_of_two_exponent(n);
45+
free_lists_[free_list_index].push_back(p);
46+
}
47+
48+
~PoolAllocator()
49+
{
50+
for (auto block : blocks_)
51+
{
52+
std::free(block);
53+
}
54+
}
55+
56+
private:
57+
size_t get_next_power_of_two_exponent(size_t n) const
58+
{
59+
return std::countr_zero(std::bit_ceil(n));
60+
}
61+
62+
void allocate_block(size_t items_in_block)
63+
{
64+
size_t block_size = std::max(items_in_block, (size_t)256) * sizeof(T);
65+
T *block = static_cast<T *>(std::malloc(block_size));
66+
if (!block)
67+
{
68+
throw std::bad_alloc();
69+
}
70+
blocks_.push_back(block);
71+
current_block_ = block;
72+
current_block_ptr_ = block;
73+
current_block_left_items_ = block_size / sizeof(T);
74+
}
75+
76+
std::array<std::vector<T *>, 32> free_lists_;
77+
std::vector<T *> blocks_;
78+
T *current_block_ = nullptr;
79+
T *current_block_ptr_ = nullptr;
80+
size_t current_block_left_items_ = 0;
81+
};
82+
83+
} // namespace osrm::util

0 commit comments

Comments
 (0)