14
14
namespace osrm ::util
15
15
{
16
16
17
- class MemoryManager
17
+ class MemoryPool
18
18
{
19
19
private:
20
- constexpr static size_t MIN_ITEMS_IN_BLOCK = 1024 ;
20
+ constexpr static size_t MIN_CHUNK_SIZE_BYTES = 4096 ;
21
21
22
22
public:
23
- static std::shared_ptr<MemoryManager > instance ()
23
+ static std::shared_ptr<MemoryPool > instance ()
24
24
{
25
- static thread_local std::shared_ptr<MemoryManager > instance;
25
+ static thread_local std::shared_ptr<MemoryPool > instance;
26
26
if (!instance)
27
27
{
28
- instance = std::shared_ptr<MemoryManager >(new MemoryManager ());
28
+ instance = std::shared_ptr<MemoryPool >(new MemoryPool ());
29
29
}
30
30
return instance;
31
31
}
32
32
33
- // TODO: alignment!!!
34
33
template <typename T>
35
- T *allocate (std::size_t n )
34
+ T *allocate (std::size_t items_count )
36
35
{
37
- size_t free_list_index = get_next_power_of_two_exponent (n * sizeof (T));
36
+ size_t free_list_index = get_next_power_of_two_exponent (items_count * sizeof (T));
38
37
auto &free_list = free_lists_[free_list_index];
39
- const auto items_in_block = 1u << free_list_index;
40
38
if (free_list.empty ())
41
39
{
42
- // Check if there is space in current block
43
- if (current_block_left_items_ < items_in_block)
40
+ const auto block_size_in_bytes = 1u << free_list_index;
41
+
42
+ // Check if there is space in current memory chunk
43
+ if (current_chunk_left_bytes_ < block_size_in_bytes)
44
44
{
45
- allocate_block<T>(items_in_block );
45
+ allocate_block<T>(block_size_in_bytes );
46
46
}
47
47
48
- free_list.push_back (current_block_ptr_ );
49
- current_block_left_items_ -= items_in_block ;
50
- current_block_ptr_ += items_in_block * sizeof (T);
48
+ free_list.push_back (current_chunk_ptr_ );
49
+ current_chunk_left_bytes_ -= block_size_in_bytes ;
50
+ current_chunk_ptr_ += items_count * sizeof (T);
51
51
}
52
52
auto ptr = static_cast <T*>(free_list.back ());
53
53
free_list.pop_back ();
@@ -61,19 +61,19 @@ class MemoryManager
61
61
free_lists_[free_list_index].push_back (p);
62
62
}
63
63
64
- ~MemoryManager ()
64
+ ~MemoryPool ()
65
65
{
66
- std::cerr << " ~MemoryManager()" << std::endl;
67
- for (auto block : blocks_)
66
+ for (auto chunk : chunks_)
68
67
{
69
- std::free (block);
68
+ // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
69
+ std::free (chunk);
70
70
}
71
71
}
72
72
73
73
private:
74
- MemoryManager () = default ;
75
- MemoryManager (const MemoryManager &) = delete ;
76
- MemoryManager &operator =(const MemoryManager &) = delete ;
74
+ MemoryPool () = default ;
75
+ MemoryPool (const MemoryPool &) = delete ;
76
+ MemoryPool &operator =(const MemoryPool &) = delete ;
77
77
78
78
size_t get_next_power_of_two_exponent (size_t n) const
79
79
{
@@ -82,26 +82,25 @@ class MemoryManager
82
82
}
83
83
84
84
template <typename T>
85
- void allocate_block (size_t items_in_block )
85
+ void allocate_block (size_t bytes )
86
86
{
87
- items_in_block = std::max (items_in_block, MIN_ITEMS_IN_BLOCK);
88
-
89
- size_t block_size = items_in_block * sizeof (T);
90
- void *block = std::malloc (block_size);
91
- if (!block)
87
+ auto chunk_size = std::max (bytes, MIN_CHUNK_SIZE_BYTES);
88
+ // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
89
+ void *chunk = std::malloc (chunk_size);
90
+ if (!chunk)
92
91
{
93
92
throw std::bad_alloc ();
94
93
}
95
- total_allocated_ += block_size ;
96
- blocks_ .push_back (block );
97
- current_block_ptr_ = static_cast <uint8_t *>(block );
98
- current_block_left_items_ = items_in_block ;
94
+ total_allocated_ += chunk_size ;
95
+ chunks_ .push_back (chunk );
96
+ current_chunk_ptr_ = static_cast <uint8_t *>(chunk );
97
+ current_chunk_left_bytes_ = chunk_size ;
99
98
}
100
99
101
100
std::array<std::vector<void *>, 32 > free_lists_;
102
- std::vector<void *> blocks_ ;
103
- uint8_t *current_block_ptr_ = nullptr ;
104
- size_t current_block_left_items_ = 0 ;
101
+ std::vector<void *> chunks_ ;
102
+ uint8_t *current_chunk_ptr_ = nullptr ;
103
+ size_t current_chunk_left_bytes_ = 0 ;
105
104
106
105
size_t total_allocated_ = 0 ;
107
106
};
@@ -112,10 +111,10 @@ class PoolAllocator
112
111
public:
113
112
using value_type = T;
114
113
115
- PoolAllocator () noexcept : pool(MemoryManager ::instance()) {};
114
+ PoolAllocator () noexcept : pool(MemoryPool ::instance()) {};
116
115
117
116
template <typename U>
118
- PoolAllocator (const PoolAllocator<U> &) noexcept : pool(MemoryManager ::instance()) {}
117
+ PoolAllocator (const PoolAllocator<U> &) noexcept : pool(MemoryPool ::instance()) {}
119
118
120
119
template <typename U>
121
120
struct rebind
@@ -133,17 +132,13 @@ class PoolAllocator
133
132
pool->deallocate <T>(p, n);
134
133
}
135
134
136
- ~PoolAllocator () {
137
- std::cerr << " ~PoolAllocator()" << std::endl;
138
- }
139
-
140
135
PoolAllocator (const PoolAllocator &) = default ;
141
136
PoolAllocator &operator =(const PoolAllocator &) = default ;
142
137
PoolAllocator (PoolAllocator &&) noexcept = default ;
143
138
PoolAllocator &operator =(PoolAllocator &&) noexcept = default ;
144
139
145
140
private:
146
- std::shared_ptr<MemoryManager > pool;
141
+ std::shared_ptr<MemoryPool > pool;
147
142
};
148
143
template <typename T, typename U>
149
144
bool operator ==(const PoolAllocator<T> &, const PoolAllocator<U> &)
0 commit comments