10 #include <botan/internal/mem_pool.h>    11 #include <botan/internal/rounding.h>    12 #include <botan/mem_ops.h>    21 Pooling_Allocator::Memory_Block::Memory_Block(
void* buf)
    23    buffer = 
static_cast<byte*
>(buf);
    25    buffer_end = buffer + (BLOCK_SIZE * BITMAP_SIZE);
    31 bool Pooling_Allocator::Memory_Block::contains(
void* ptr,
    34    return ((buffer <= ptr) &&
    35            (buffer_end >= static_cast<byte*>(ptr) + length * BLOCK_SIZE));
    43    if(n == 0 || n > BITMAP_SIZE)
    57    bitmap_type mask = (
static_cast<bitmap_type
>(1) << n) - 1;
    65       if((bitmap & mask) == 0)
    75    return buffer + offset * BLOCK_SIZE;
    81 void Pooling_Allocator::Memory_Block::free(
void* ptr, 
size_t blocks)
    83    clear_mem(static_cast<byte*>(ptr), blocks * BLOCK_SIZE);
    85    const size_t offset = (
static_cast<byte*
>(ptr) - buffer) / BLOCK_SIZE;
    87    if(offset == 0 && blocks == BITMAP_SIZE)
    91       for(
size_t j = 0; j != blocks; ++j)
    92          bitmap &= ~(static_cast<bitmap_type>(1) << (j+offset));
   101    last_used = blocks.begin();
   112       throw Invalid_State(
"Pooling_Allocator: Never released memory");
   125    for(
size_t j = 0; j != allocated.size(); ++j)
   126       dealloc_block(allocated[j].first, allocated[j].second);
   135    const size_t BITMAP_SIZE = Memory_Block::bitmap_size();
   136    const size_t BLOCK_SIZE = Memory_Block::block_size();
   140    if(n <= BITMAP_SIZE * BLOCK_SIZE)
   142       const size_t block_no = 
round_up(n, BLOCK_SIZE) / BLOCK_SIZE;
   144       byte* mem = allocate_blocks(block_no);
   148       get_more_core(BOTAN_MEM_POOL_CHUNK_SIZE);
   150       mem = allocate_blocks(block_no);
   157    void* new_buf = alloc_block(n);
   169    const size_t BITMAP_SIZE = Memory_Block::bitmap_size();
   170    const size_t BLOCK_SIZE = Memory_Block::block_size();
   172    if(ptr == 0 || n == 0)
   177    if(n > BITMAP_SIZE * BLOCK_SIZE)
   178       dealloc_block(ptr, n);
   181       const size_t block_no = 
round_up(n, BLOCK_SIZE) / BLOCK_SIZE;
   183       std::vector<Memory_Block>::iterator i =
   184          std::lower_bound(blocks.begin(), blocks.end(), Memory_Block(ptr));
   186       if(i == blocks.end() || !i->contains(ptr, block_no))
   187          throw Invalid_State(
"Pointer released to the wrong allocator");
   189       i->free(ptr, block_no);
   196 byte* Pooling_Allocator::allocate_blocks(
size_t n)
   201    std::vector<Memory_Block>::iterator i = last_used;
   205       byte* mem = i->alloc(n);
   213       if(i == blocks.end())
   216    while(i != last_used);
   224 void Pooling_Allocator::get_more_core(
size_t in_bytes)
   226    const size_t BITMAP_SIZE = Memory_Block::bitmap_size();
   227    const size_t BLOCK_SIZE = Memory_Block::block_size();
   229    const size_t TOTAL_BLOCK_SIZE = BLOCK_SIZE * BITMAP_SIZE;
   232    in_bytes = std::min<size_t>(in_bytes, 1024 * 1024);
   234    const size_t in_blocks = 
round_up(in_bytes, BLOCK_SIZE) / TOTAL_BLOCK_SIZE;
   235    const size_t to_allocate = in_blocks * TOTAL_BLOCK_SIZE;
   237    void* ptr = alloc_block(to_allocate);
   241    allocated.push_back(std::make_pair(ptr, to_allocate));
   243    for(
size_t j = 0; j != in_blocks; ++j)
   245       byte* byte_ptr = 
static_cast<byte*
>(ptr);
   246       blocks.push_back(Memory_Block(byte_ptr + j * TOTAL_BLOCK_SIZE));
   249    std::sort(blocks.begin(), blocks.end());
   250    last_used = std::lower_bound(blocks.begin(), blocks.end(),
 
void deallocate(void *, size_t)
void clear_mem(T *ptr, size_t n)
Pooling_Allocator(Mutex *mutex)
T round_up(T n, T align_to)