BitMagic-C++
bmalloc.h
Go to the documentation of this file.
1#ifndef BMALLOC__H__INCLUDED__
2#define BMALLOC__H__INCLUDED__
3/*
4Copyright(c) 2002-2017 Anatoliy Kuznetsov(anatoliy_kuznetsov at yahoo.com)
5
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing, software
13distributed under the License is distributed on an "AS IS" BASIS,
14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15See the License for the specific language governing permissions and
16limitations under the License.
17
18For more information please visit: http://bitmagic.io
19*/
20
21/*! \file bmalloc.h
22 \brief Default SIMD friendly allocator
23*/
24
25#include <stdlib.h>
26#include <new>
27
28namespace bm
29{
30
31#if defined(BMSSE2OPT) || defined(BMSSE42OPT)
32#define BM_ALLOC_ALIGN 16
33#endif
34#if defined(BMAVX2OPT)
35#define BM_ALLOC_ALIGN 32
36#endif
37#if defined(BMAVX512OPT)
38#define BM_ALLOC_ALIGN 64
39#endif
40
41
42/*!
43 @defgroup alloc Allocator
44 Memory allocation for bvector
45
46 @ingroup bvector
47
48 @{
49 */
50
51/*!
52 @brief Default malloc based bitblock allocator class.
53
54 Functions allocate and deallocate conform to STL allocator specs.
55 @ingroup alloc
56*/
58{
59public:
60 /**
61 The member function allocates storage for an array of n bm::word_t
62 elements, by calling malloc.
63 @return pointer to the allocated memory.
64 */
65 static bm::word_t* allocate(size_t n, const void *)
66 {
67 bm::word_t* ptr;
68
69#if defined(BM_ALLOC_ALIGN)
70 #ifdef _MSC_VER
71 ptr = (bm::word_t*) ::_aligned_malloc(n * sizeof(bm::word_t), BM_ALLOC_ALIGN);
72 #else
73 ptr = (bm::word_t*) ::_mm_malloc(n * sizeof(bm::word_t), BM_ALLOC_ALIGN);
74 #endif
75#else
76 ptr = (bm::word_t*) ::malloc(n * sizeof(bm::word_t));
77#endif
78 if (!ptr)
79 throw std::bad_alloc();
80 return ptr;
81 }
82
83 /**
84 The member function frees storage for an array of n bm::word_t
85 elements, by calling free.
86 */
87 static void deallocate(bm::word_t* p, size_t) BMNOEXCEPT
88 {
89#ifdef BM_ALLOC_ALIGN
90 # ifdef _MSC_VER
91 ::_aligned_free(p);
92 #else
93 ::_mm_free(p);
94 # endif
95#else
96 ::free(p);
97#endif
98 }
99
100};
101
102
103
104/*! @brief Default malloc based bitblock allocator class.
105
106 Functions allocate and deallocate conform to STL allocator specs.
107*/
109{
110public:
111 /**
112 The member function allocates storage for an array of n void*
113 elements, by calling malloc.
114 @return pointer to the allocated memory.
115 */
116 static void* allocate(size_t n, const void *)
117 {
118 void* ptr;
119#if defined(BM_ALLOC_ALIGN)
120 #ifdef _MSC_VER
121 ptr = (bm::word_t*) ::_aligned_malloc(n * sizeof(void*), BM_ALLOC_ALIGN);
122 #else
123 ptr = (bm::word_t*) ::_mm_malloc(n * sizeof(void*), BM_ALLOC_ALIGN);
124 #endif
125#else
126 ptr = (bm::word_t*) ::malloc(n * sizeof(void*));
127#endif
128// void* ptr = ::malloc(n * sizeof(void*));
129 if (!ptr)
130 throw std::bad_alloc();
131 return ptr;
132 }
133
134 /**
135 The member function frees storage for an array of n bm::word_t
136 elements, by calling free.
137 */
138 static void deallocate(void* p, size_t) BMNOEXCEPT
139 {
140#ifdef BM_ALLOC_ALIGN
141 # ifdef _MSC_VER
142 ::_aligned_free(p);
143 #else
144 ::_mm_free(p);
145 # endif
146#else
147 ::free(p);
148#endif
149 }
150};
151
152/*!
153 @brief Pool of pointers to buffer cyclic allocations
154*/
156{
157public:
159 {
161 };
162
163 pointer_pool_array() : pool_ptr_(0), size_(0)
164 {
165 allocate_pool(n_pool_max_size);
166 }
167
170
172 {
173 BM_ASSERT(size_ == 0); // at destruction point should be empty (otherwise it is a leak)
174 free_pool();
175 }
176
177 /// Push pointer to the pool (if it is not full)
178 ///
179 /// @return 0 if pointer is not accepted (pool is full)
180 unsigned push(void* ptr) BMNOEXCEPT
181 {
182 if (size_ == n_pool_max_size - 1)
183 return 0;
184 pool_ptr_[size_++] = ptr;
185 return size_;
186 }
187
188 /// Get a pointer if there are any vacant
189 ///
191 {
192 if (!size_)
193 return 0;
194 return pool_ptr_[--size_];
195 }
196
197 /// return stack size
198 ///
199 unsigned size() const BMNOEXCEPT { return size_; }
200
201private:
202 void allocate_pool(size_t pool_size)
203 {
204 BM_ASSERT(!pool_ptr_);
205 pool_ptr_ = (void**)::malloc(sizeof(void*) * pool_size);
206 if (!pool_ptr_)
207 throw std::bad_alloc();
208 }
209
210 void free_pool() BMNOEXCEPT
211 {
212 ::free(pool_ptr_);
213 }
214private:
215 void** pool_ptr_; ///< array of pointers in the pool
216 unsigned size_; ///< current size
217};
218
219/**
220 Allocation pool object
221*/
222template<class BA, class PA>
224{
225public:
228
229public:
230
233
234 void set_block_limit(size_t limit) BMNOEXCEPT
235 { block_limit_ = limit; }
236
238 {
240 if (!ptr)
241 ptr = block_alloc_.allocate(bm::set_block_size, 0);
242 return ptr;
243 }
244
246 {
247 BM_ASSERT(IS_VALID_ADDR(block));
248 if (block_limit_) // soft limit set
249 {
251 {
252 block_alloc_.deallocate(block, bm::set_block_size);
253 return;
254 }
255 }
256 if (!block_pool_.push(block))
257 block_alloc_.deallocate(block, bm::set_block_size);
258 }
259
261 {
262 bm::word_t* block;
263 do
264 {
265 block = (bm::word_t*)block_pool_.pop();
266 if (block)
267 block_alloc_.deallocate(block, bm::set_block_size);
268 } while (block);
269 }
270
271 /// return stack size
272 ///
273 unsigned size() const BMNOEXCEPT { return block_pool_.size(); }
274
275protected:
278 size_t block_limit_ = 0; ///< soft limit for the pool of blocks
279};
280
281
282/*! @brief BM style allocator adapter.
283
284 Template takes parameters:
285 BA - allocator object for bit blocks
286 PA - allocator object for pointer blocks
287 APool - Allocation pool
288*/
289template<class BA, class PA, class APool>
291{
292public:
293
296 typedef APool allocator_pool_type;
297
298public:
299
300 mem_alloc(const BA& block_alloc = BA(), const PA& ptr_alloc = PA()) BMNOEXCEPT
301 : block_alloc_(block_alloc),
302 ptr_alloc_(ptr_alloc),
304 {}
305
307 : block_alloc_(ma.block_alloc_),
308 ptr_alloc_(ma.ptr_alloc_),
309 alloc_pool_p_(0) // do not inherit pool (has to be explicitly defined)
310 {}
311
313 {
314 block_alloc_ = ma.block_alloc_;
315 ptr_alloc_ = ma.ptr_alloc_;
316 // alloc_pool_p_ - do not inherit pool (has to be explicitly defined)
317 return *this;
318 }
319
320 /*! @brief Returns copy of the block allocator object
321 */
323 {
324 return BA(block_alloc_);
325 }
326
327 /*! @brief Returns copy of the ptr allocator object
328 */
330 {
331 return PA(block_alloc_);
332 }
333
334 /*! @brief set pointer to external pool */
336 {
337 alloc_pool_p_ = pool;
338 }
339
340 /*! @brief get pointer to allocation pool (if set) */
342 {
343 return alloc_pool_p_;
344 }
345
346 /*! @brief Allocates and returns bit block.
347 @param alloc_factor
348 indicated how many blocks we want to allocate in chunk
349 total allocation is going to be bm::set_block_size * alloc_factor
350 Default allocation factor is 1
351 */
352 bm::word_t* alloc_bit_block(unsigned alloc_factor = 1)
353 {
354 if (alloc_pool_p_ && alloc_factor == 1)
355 return alloc_pool_p_->alloc_bit_block();
356 return block_alloc_.allocate(bm::set_block_size * alloc_factor, 0);
357 }
358
359 /*! @brief Frees bit block allocated by alloc_bit_block.
360 */
361 void free_bit_block(bm::word_t* block, size_t alloc_factor = 1) BMNOEXCEPT
362 {
363 BM_ASSERT(IS_VALID_ADDR(block));
364 if (alloc_pool_p_ && alloc_factor == 1)
365 alloc_pool_p_->free_bit_block(block);
366 else
367 block_alloc_.deallocate(block, bm::set_block_size * alloc_factor);
368 }
369
370 /*! @brief Allocates GAP block using bit block allocator (BA).
371
372 GAP blocks in BM library belong to levels. Each level has a
373 correspondent length described in bm::gap_len_table<>
374
375 @param level GAP block level.
376 @param glevel_len table of level lengths
377 */
379 const bm::gap_word_t* glevel_len)
380 {
381 BM_ASSERT(level < bm::gap_levels);
382 unsigned len =
383 (unsigned)(glevel_len[level] / (sizeof(bm::word_t) / sizeof(bm::gap_word_t)));
384
385 return (bm::gap_word_t*)block_alloc_.allocate(len, 0);
386 }
387
388 /*! @brief Frees GAP block using bot block allocator (BA)
389 */
391 const bm::gap_word_t* glevel_len)
392 {
394
395 unsigned len = bm::gap_capacity(block, glevel_len);
396 len /= (unsigned)(sizeof(bm::word_t) / sizeof(bm::gap_word_t));
397 block_alloc_.deallocate((bm::word_t*)block, len);
398 }
399
400 /*! @brief Allocates block of pointers.
401 */
402 void* alloc_ptr(size_t size)
403 {
404 BM_ASSERT(size);
405 return ptr_alloc_.allocate(size, 0);
406 }
407
408 /*! @brief Frees block of pointers.
409 */
410 void free_ptr(void* p, size_t size) BMNOEXCEPT
411 {
412 if (p)
413 ptr_alloc_.deallocate(p, size);
414 }
415
416 /**
417 Get access to block allocator
418 */
420protected:
424};
425
428
429/** @} */
430
431
432/// Aligned malloc (unlike classic malloc it throws bad_alloc exception)
433///
434/// To allocate temp bit-block use: bm::aligned_new_malloc(bm::set_block_alloc_size);
435/// @internal
436inline
437void* aligned_new_malloc(size_t size)
438{
439 void* ptr;
440
441#ifdef BM_ALLOC_ALIGN
442#ifdef _MSC_VER
443 ptr = ::_aligned_malloc(size, BM_ALLOC_ALIGN);
444#else
445 ptr = ::_mm_malloc(size, BM_ALLOC_ALIGN);
446#endif
447#else
448 ptr = ::malloc(size);
449#endif
450 if (!ptr)
451 {
452#ifndef BM_NO_STL
453 throw std::bad_alloc();
454#else
455 BM_THROW(BM_ERR_BADALLOC);
456#endif
457 }
458 return ptr;
459}
460
461/// Aligned free
462///
463/// @internal
464inline
466{
467 if (!ptr)
468 return;
469#ifdef BM_ALLOC_ALIGN
470# ifdef _MSC_VER
471 ::_aligned_free(ptr);
472#else
473 ::_mm_free(ptr);
474# endif
475#else
476 ::free(ptr);
477#endif
478}
479
480
481
482#undef BM_ALLOC_ALIGN
483
484} // namespace bm
485
486
487#endif
#define BM_ALLOC_ALIGN
Definition: bmalloc.h:35
#define BM_DEFAULT_POOL_SIZE
Definition: bmconst.h:43
#define IS_VALID_ADDR(addr)
Definition: bmdef.h:161
#define BMNOEXCEPT
Definition: bmdef.h:82
#define BM_ASSERT
Definition: bmdef.h:139
Allocation pool object.
Definition: bmalloc.h:224
void set_block_limit(size_t limit) BMNOEXCEPT
Definition: bmalloc.h:234
void free_bit_block(bm::word_t *block) BMNOEXCEPT
Definition: bmalloc.h:245
size_t block_limit_
soft limit for the pool of blocks
Definition: bmalloc.h:278
bm::word_t * alloc_bit_block()
Definition: bmalloc.h:237
unsigned size() const BMNOEXCEPT
return stack size
Definition: bmalloc.h:273
void free_pools() BMNOEXCEPT
Definition: bmalloc.h:260
pointer_pool_array block_pool_
Definition: bmalloc.h:276
BA block_allocator_type
Definition: bmalloc.h:226
PA ptr_allocator_type
Definition: bmalloc.h:227
Default malloc based bitblock allocator class.
Definition: bmalloc.h:58
static bm::word_t * allocate(size_t n, const void *)
The member function allocates storage for an array of n bm::word_t elements, by calling malloc.
Definition: bmalloc.h:65
static void deallocate(bm::word_t *p, size_t) BMNOEXCEPT
The member function frees storage for an array of n bm::word_t elements, by calling free.
Definition: bmalloc.h:87
BM style allocator adapter.
Definition: bmalloc.h:291
void free_ptr(void *p, size_t size) BMNOEXCEPT
Frees block of pointers.
Definition: bmalloc.h:410
void set_pool(allocator_pool_type *pool) BMNOEXCEPT
set pointer to external pool
Definition: bmalloc.h:335
PA ptr_allocator_type
Definition: bmalloc.h:295
mem_alloc & operator=(const mem_alloc &ma) BMNOEXCEPT
Definition: bmalloc.h:312
APool allocator_pool_type
Definition: bmalloc.h:296
mem_alloc(const BA &block_alloc=BA(), const PA &ptr_alloc=PA()) BMNOEXCEPT
Definition: bmalloc.h:300
void * alloc_ptr(size_t size)
Allocates block of pointers.
Definition: bmalloc.h:402
void free_bit_block(bm::word_t *block, size_t alloc_factor=1) BMNOEXCEPT
Frees bit block allocated by alloc_bit_block.
Definition: bmalloc.h:361
allocator_pool_type * get_pool() BMNOEXCEPT
get pointer to allocation pool (if set)
Definition: bmalloc.h:341
bm::gap_word_t * alloc_gap_block(unsigned level, const bm::gap_word_t *glevel_len)
Allocates GAP block using bit block allocator (BA).
Definition: bmalloc.h:378
mem_alloc(const mem_alloc &ma) BMNOEXCEPT
Definition: bmalloc.h:306
BA block_allocator_type
Definition: bmalloc.h:294
block_allocator_type get_block_allocator() const BMNOEXCEPT
Returns copy of the block allocator object.
Definition: bmalloc.h:322
bm::word_t * alloc_bit_block(unsigned alloc_factor=1)
Allocates and returns bit block.
Definition: bmalloc.h:352
BA block_alloc_
Definition: bmalloc.h:421
ptr_allocator_type get_ptr_allocator() const BMNOEXCEPT
Returns copy of the ptr allocator object.
Definition: bmalloc.h:329
void free_gap_block(bm::gap_word_t *block, const bm::gap_word_t *glevel_len)
Frees GAP block using bot block allocator (BA)
Definition: bmalloc.h:390
allocator_pool_type * alloc_pool_p_
Definition: bmalloc.h:423
BA & get_block_alloc() BMNOEXCEPT
Get access to block allocator.
Definition: bmalloc.h:419
Pool of pointers to buffer cyclic allocations.
Definition: bmalloc.h:156
void * pop() BMNOEXCEPT
Get a pointer if there are any vacant.
Definition: bmalloc.h:190
pointer_pool_array(const pointer_pool_array &)=delete
pointer_pool_array & operator=(const pointer_pool_array &)=delete
unsigned size() const BMNOEXCEPT
return stack size
Definition: bmalloc.h:199
unsigned push(void *ptr) BMNOEXCEPT
Push pointer to the pool (if it is not full)
Definition: bmalloc.h:180
Default malloc based bitblock allocator class.
Definition: bmalloc.h:109
static void * allocate(size_t n, const void *)
The member function allocates storage for an array of n void* elements, by calling malloc.
Definition: bmalloc.h:116
static void deallocate(void *p, size_t) BMNOEXCEPT
The member function frees storage for an array of n bm::word_t elements, by calling free.
Definition: bmalloc.h:138
bm::alloc_pool< block_allocator, ptr_allocator > standard_alloc_pool
Definition: bmalloc.h:426
bm::mem_alloc< block_allocator, ptr_allocator, standard_alloc_pool > standard_allocator
Definition: bmalloc.h:427
unsigned gap_capacity(const T *BMRESTRICT buf, const T *BMRESTRICT glevel_len) BMNOEXCEPT
Returs GAP block capacity.
Definition: bmfunc.h:1591
Definition: bm.h:78
unsigned int word_t
Definition: bmconst.h:39
void aligned_free(void *ptr) BMNOEXCEPT
Aligned free.
Definition: bmalloc.h:465
void * aligned_new_malloc(size_t size)
Aligned malloc (unlike classic malloc it throws bad_alloc exception)
Definition: bmalloc.h:437
const unsigned gap_levels
Definition: bmconst.h:85
const unsigned set_block_size
Definition: bmconst.h:55
unsigned short gap_word_t
Definition: bmconst.h:78