95template <
typename T>
class stl_pool_allocator {
98 typedef value_type* pointer;
99 typedef const value_type* const_pointer;
100 typedef value_type& reference;
101 typedef const value_type& const_reference;
102 typedef std::size_t size_type;
103 typedef std::ptrdiff_t difference_type;
105 template <
typename U>
struct rebind {
typedef stl_pool_allocator<U> other; };
107 stl_pool_allocator() =
default;
109 stl_pool_allocator(stl_pool_allocator
const&)
noexcept {}
113 ~stl_pool_allocator() NOEXCEPT {}
116 pointer address(reference r) {
return std::addressof(r); }
117 const_pointer address(const_reference r) {
return std::addressof(r); }
119 pointer allocate(size_type n,
const void* = 0) {
120 if(n > std::numeric_limits<std::size_t>::max() /
sizeof(value_type))
121 throw std::bad_array_new_length();
124 return static_cast<value_type*
>(util::pool_allocator<
sizeof(value_type)>::get().allocate());
126 return static_cast<value_type*
>(util::pool_allocator<
sizeof(value_type) * 2>::get().allocate());
128 return static_cast<value_type*
>(util::pool_allocator<
sizeof(value_type) * 4>::get().allocate());
130 return static_cast<value_type*
>(util::pool_allocator<
sizeof(value_type) * 8>::get().allocate());
132 return static_cast<value_type*
>(util::pool_allocator<
sizeof(value_type) * 16>::get().allocate());
134 return static_cast<value_type*
>(util::pool_allocator<
sizeof(value_type) * 32>::get().allocate());
136 return static_cast<value_type*
>(util::pool_allocator<
sizeof(value_type) * 64>::get().allocate());
138 return static_cast<value_type*
>(util::pool_allocator<
sizeof(value_type) * 128>::get().allocate());
140 return static_cast<value_type*
>(util::pool_allocator<
sizeof(value_type) * 256>::get().allocate());
142 return static_cast<value_type*
>(util::pool_allocator<
sizeof(value_type) * 512, 2048>::get().allocate());
144 return static_cast<value_type*
>(util::pool_allocator<
sizeof(value_type) * 1024, 1024>::get().allocate());
146 return static_cast<value_type*
>(util::pool_allocator<
sizeof(value_type) * 2048, 512>::get().allocate());
148 return static_cast<value_type*
>(util::pool_allocator<
sizeof(value_type) * 4096, 256>::get().allocate());
150 if(
auto p =
static_cast<value_type*
>(std::malloc(n *
sizeof(value_type))))
152 throw std::bad_alloc();
156 void deallocate(T* p, size_type n)
noexcept {
159 return util::pool_allocator<
sizeof(value_type)>::get().free(p);
161 return util::pool_allocator<
sizeof(value_type) * 2>::get().free(p);
163 return util::pool_allocator<
sizeof(value_type) * 4>::get().free(p);
165 return util::pool_allocator<
sizeof(value_type) * 8>::get().free(p);
167 return util::pool_allocator<
sizeof(value_type) * 16>::get().free(p);
169 return util::pool_allocator<
sizeof(value_type) * 32>::get().free(p);
171 return util::pool_allocator<
sizeof(value_type) * 64>::get().free(p);
173 return util::pool_allocator<
sizeof(value_type) * 128>::get().free(p);
175 return util::pool_allocator<
sizeof(value_type) * 256>::get().free(p);
177 return util::pool_allocator<
sizeof(value_type) * 512>::get().free(p);
179 return util::pool_allocator<
sizeof(value_type) * 1024>::get().free(p);
181 return util::pool_allocator<
sizeof(value_type) * 2048>::get().free(p);
183 return util::pool_allocator<
sizeof(value_type) * 4096>::get().free(p);
189 size_type max_size() const noexcept {
return std::numeric_limits<size_type>::max() /
sizeof(T); }
191 bool operator==(stl_pool_allocator
const&) {
return true; }
192 bool operator!=(stl_pool_allocator
const& oAllocator) {
return !operator==(oAllocator); }
203 auto* check = getenv(
"TLM_MM_CHECK");
206 std::cerr << __FUNCTION__ <<
": detected memory leak upon destruction, " << diff <<
" of " <<
get_capacity()
207 <<
" entries are not free'd" << std::endl;
209 if(check && _stricmp(check,
"DEBUG") == 0) {
211 if(check && strcasecmp(check,
"DEBUG") == 0) {
213 std::vector<std::pair<void*, uint64_t>> elems(used_blocks.begin(), used_blocks.end());
214 std::sort(elems.begin(), elems.end(), [](std::pair<void*, uint64_t>
const& a, std::pair<void*, uint64_t>
const& b) ->
bool {
215 return a.second == b.second ? a.first < b.first : a.second < b.second;
217 std::cerr <<
"The 10 blocks with smallest id are:\n";
218 for(
size_t i = 0; i < std::min<decltype(i)>(10UL, elems.size()); ++i) {
219 std::cerr <<
"\taddr=" << elems[i].first <<
", id=" << elems[i].second <<
"\n";