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 if (!ptr)
129 throw std::bad_alloc();
130 return ptr;
131 }
132
133 /**
134 The member function frees storage for an array of n bm::word_t
135 elements, by calling free.
136 */
137 static void deallocate(void* p, size_t) BMNOEXCEPT
138 {
139#ifdef BM_ALLOC_ALIGN
140 # ifdef _MSC_VER
141 ::_aligned_free(p);
142 #else
143 ::_mm_free(p);
144 # endif
145#else
146 ::free(p);
147#endif
148 }
149};
150
151/*!
152 @brief Pool of pointers to buffer cyclic allocations
153*/
155{
156public:
161
162 pointer_pool_array() : pool_ptr_(0), size_(0)
163 {
164 allocate_pool(n_pool_max_size);
165 }
166
169
171 {
172 BM_ASSERT(size_ == 0); // at destruction point should be empty (otherwise it is a leak)
173 free_pool();
174 }
175
176 /// Push pointer to the pool (if it is not full)
177 ///
178 /// @return 0 if pointer is not accepted (pool is full)
179 unsigned push(void* ptr) BMNOEXCEPT
180 {
181 if (size_ == n_pool_max_size - 1)
182 return 0;
183 pool_ptr_[size_++] = ptr;
184 return size_;
185 }
186
187 /// Get a pointer if there are any vacant
188 ///
190 {
191 if (!size_)
192 return 0;
193 return pool_ptr_[--size_];
194 }
195
196 /// return stack size
197 ///
198 unsigned size() const BMNOEXCEPT { return size_; }
199
200private:
201 void allocate_pool(size_t pool_size)
202 {
203 BM_ASSERT(!pool_ptr_);
204 pool_ptr_ = (void**)::malloc(sizeof(void*) * pool_size);
205 if (!pool_ptr_)
206 throw std::bad_alloc();
207 }
208
209 void free_pool() BMNOEXCEPT
210 {
211 ::free(pool_ptr_);
212 }
213private:
214 void** pool_ptr_; ///< array of pointers in the pool
215 unsigned size_; ///< current size
216};
217
218/**
219 Allocation pool object
220*/
221template<class BA, class PA>
223{
224public:
227
228public:
229
232
233 void set_block_limit(size_t limit) BMNOEXCEPT
234 { block_limit_ = limit; }
235
237 {
238 bm::word_t* ptr = (bm::word_t*)block_pool_.pop();
239 if (!ptr)
240 ptr = block_alloc_.allocate(bm::set_block_size, 0);
241 return ptr;
242 }
243
245 {
246 BM_ASSERT(IS_VALID_ADDR(block));
247 if (block_limit_) // soft limit set
248 {
249 if (block_pool_.size() >= block_limit_)
250 {
251 block_alloc_.deallocate(block, bm::set_block_size);
252 return;
253 }
254 }
255 if (!block_pool_.push(block))
256 block_alloc_.deallocate(block, bm::set_block_size);
257 }
258
260 {
261 bm::word_t* block;
262 do
263 {
264 block = (bm::word_t*)block_pool_.pop();
265 if (block)
266 block_alloc_.deallocate(block, bm::set_block_size);
267 } while (block);
268 }
269
270 /// return stack size
271 ///
272 unsigned size() const BMNOEXCEPT { return block_pool_.size(); }
273
274protected:
277 size_t block_limit_ = 0; ///< soft limit for the pool of blocks
278};
279
280
281/*! @brief BM style allocator adapter.
282
283 Template takes parameters:
284 BA - allocator object for bit blocks
285 PA - allocator object for pointer blocks
286 APool - Allocation pool
287*/
288template<class BA, class PA, class APool>
290{
291public:
292
295 typedef APool allocator_pool_type;
296
297public:
298
299 mem_alloc(const BA& block_alloc = BA(), const PA& ptr_alloc = PA()) BMNOEXCEPT
300 : block_alloc_(block_alloc),
301 ptr_alloc_(ptr_alloc),
303 {}
304
306 : block_alloc_(ma.block_alloc_),
307 ptr_alloc_(ma.ptr_alloc_),
308 alloc_pool_p_(0) // do not inherit pool (has to be explicitly defined)
309 {}
310
312 {
313 block_alloc_ = ma.block_alloc_;
314 ptr_alloc_ = ma.ptr_alloc_;
315 // alloc_pool_p_ - do not inherit pool (has to be explicitly defined)
316 return *this;
317 }
318
319 /*! @brief Returns copy of the block allocator object
320 */
325
326 /*! @brief Returns copy of the ptr allocator object
327 */
329 {
330 return PA(block_alloc_);
331 }
332
333 /*! @brief set pointer to external pool */
335 {
336 alloc_pool_p_ = pool;
337 }
338
339 /*! @brief get pointer to allocation pool (if set) */
344
345 /*! @brief Allocates and returns bit block.
346 @param alloc_factor
347 indicated how many blocks we want to allocate in chunk
348 total allocation is going to be bm::set_block_size * alloc_factor
349 Default allocation factor is 1
350 */
351 bm::word_t* alloc_bit_block(unsigned alloc_factor = 1)
352 {
353 if (alloc_pool_p_ && alloc_factor == 1)
354 return alloc_pool_p_->alloc_bit_block();
355 return block_alloc_.allocate(bm::set_block_size * alloc_factor, 0);
356 }
357
358 /*! @brief Frees bit block allocated by alloc_bit_block.
359 */
360 void free_bit_block(bm::word_t* block, size_t alloc_factor = 1) BMNOEXCEPT
361 {
362 BM_ASSERT(IS_VALID_ADDR(block));
363 if (alloc_pool_p_ && alloc_factor == 1)
364 alloc_pool_p_->free_bit_block(block);
365 else
366 block_alloc_.deallocate(block, bm::set_block_size * alloc_factor);
367 }
368
369 /*! @brief Allocates GAP block using bit block allocator (BA).
370
371 GAP blocks in BM library belong to levels. Each level has a
372 correspondent length described in bm::gap_len_table<>
373
374 @param level GAP block level.
375 @param glevel_len table of level lengths
376 */
378 const bm::gap_word_t* glevel_len)
379 {
380 BM_ASSERT(level < bm::gap_levels);
381 unsigned len =
382 (unsigned)(glevel_len[level] / (sizeof(bm::word_t) / sizeof(bm::gap_word_t)));
383
384 return (bm::gap_word_t*)block_alloc_.allocate(len, 0);
385 }
386
387 /*! @brief Frees GAP block using bot block allocator (BA)
388 */
390 const bm::gap_word_t* glevel_len)
391 {
393
394 unsigned len = bm::gap_capacity(block, glevel_len);
395 len /= (unsigned)(sizeof(bm::word_t) / sizeof(bm::gap_word_t));
396 block_alloc_.deallocate((bm::word_t*)block, len);
397 }
398
399 /*! @brief Allocates block of pointers.
400 */
401 void* alloc_ptr(size_t size)
402 {
403 BM_ASSERT(size);
404 return ptr_alloc_.allocate(size, 0);
405 }
406
407 /*! @brief Frees block of pointers.
408 */
409 void free_ptr(void* p, size_t size) BMNOEXCEPT
410 {
411 if (p)
412 ptr_alloc_.deallocate(p, size);
413 }
414
415 /**
416 Get access to block allocator
417 */
419protected:
423};
424
427
428/** @} */
429
430
431/// Aligned malloc (unlike classic malloc it throws bad_alloc exception)
432///
433/// To allocate temp bit-block use: bm::aligned_new_malloc(bm::set_block_alloc_size);
434/// @internal
435inline
436void* aligned_new_malloc(size_t size)
437{
438 void* ptr;
439
440#ifdef BM_ALLOC_ALIGN
441#ifdef _MSC_VER
442 ptr = ::_aligned_malloc(size, BM_ALLOC_ALIGN);
443#else
444 ptr = ::_mm_malloc(size, BM_ALLOC_ALIGN);
445#endif
446#else
447 ptr = ::malloc(size);
448#endif
449 if (!ptr)
450 {
451#ifndef BM_NO_STL
452 throw std::bad_alloc();
453#else
454 BM_THROW(BM_ERR_BADALLOC);
455#endif
456 }
457 return ptr;
458}
459
460/// Aligned free
461///
462/// @internal
463inline
465{
466 if (!ptr)
467 return;
468#ifdef BM_ALLOC_ALIGN
469# ifdef _MSC_VER
470 ::_aligned_free(ptr);
471#else
472 ::_mm_free(ptr);
473# endif
474#else
475 ::free(ptr);
476#endif
477}
478
479
480
481
482} // namespace bm
483
484
485#endif
#define BM_ALLOC_ALIGN
Definition bmalloc.h:32
#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:223
void set_block_limit(size_t limit) BMNOEXCEPT
Definition bmalloc.h:233
void free_bit_block(bm::word_t *block) BMNOEXCEPT
Definition bmalloc.h:244
bm::word_t * alloc_bit_block()
Definition bmalloc.h:236
unsigned size() const BMNOEXCEPT
return stack size
Definition bmalloc.h:272
void free_pools() BMNOEXCEPT
Definition bmalloc.h:259
BA block_allocator_type
Definition bmalloc.h:225
PA ptr_allocator_type
Definition bmalloc.h:226
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:290
void free_ptr(void *p, size_t size) BMNOEXCEPT
Frees block of pointers.
Definition bmalloc.h:409
bm::word_t * alloc_bit_block(unsigned alloc_factor=1)
Allocates and returns bit block.
Definition bmalloc.h:351
BA & get_block_alloc() BMNOEXCEPT
Get access to block allocator.
Definition bmalloc.h:418
void * alloc_ptr(size_t size)
Allocates block of pointers.
Definition bmalloc.h:401
void set_pool(allocator_pool_type *pool) BMNOEXCEPT
set pointer to external pool
Definition bmalloc.h:334
PA ptr_allocator_type
Definition bmalloc.h:294
APool allocator_pool_type
Definition bmalloc.h:295
mem_alloc(const BA &block_alloc=BA(), const PA &ptr_alloc=PA()) BMNOEXCEPT
Definition bmalloc.h:299
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:377
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:360
mem_alloc(const mem_alloc &ma) BMNOEXCEPT
Definition bmalloc.h:305
BA block_allocator_type
Definition bmalloc.h:293
block_allocator_type get_block_allocator() const BMNOEXCEPT
Returns copy of the block allocator object.
Definition bmalloc.h:321
allocator_pool_type * get_pool() BMNOEXCEPT
get pointer to allocation pool (if set)
Definition bmalloc.h:340
ptr_allocator_type get_ptr_allocator() const BMNOEXCEPT
Returns copy of the ptr allocator object.
Definition bmalloc.h:328
mem_alloc & operator=(const mem_alloc &ma) BMNOEXCEPT
Definition bmalloc.h:311
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:389
Pool of pointers to buffer cyclic allocations.
Definition bmalloc.h:155
void * pop() BMNOEXCEPT
Get a pointer if there are any vacant.
Definition bmalloc.h:189
pointer_pool_array(const pointer_pool_array &)=delete
unsigned size() const BMNOEXCEPT
return stack size
Definition bmalloc.h:198
pointer_pool_array & operator=(const pointer_pool_array &)=delete
unsigned push(void *ptr) BMNOEXCEPT
Push pointer to the pool (if it is not full).
Definition bmalloc.h:179
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:137
bm::alloc_pool< block_allocator, ptr_allocator > standard_alloc_pool
Definition bmalloc.h:425
bm::mem_alloc< block_allocator, ptr_allocator, standard_alloc_pool > standard_allocator
Definition bmalloc.h:426
unsigned gap_capacity(const T *BMRESTRICT buf, const T *BMRESTRICT glevel_len) BMNOEXCEPT
Returs GAP block capacity.
Definition bmfunc.h:1619
Definition bm.h:78
unsigned int word_t
Definition bmconst.h:39
void aligned_free(void *ptr) BMNOEXCEPT
Aligned free.
Definition bmalloc.h:464
void * aligned_new_malloc(size_t size)
Aligned malloc (unlike classic malloc it throws bad_alloc exception).
Definition bmalloc.h:436
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