/** * Construct a resizable chunk allocator initially holding the * specified number of bytes. * * @throws std::runtime_error if the underlying malloc is not 8-byte * aligned. */ chunk_alloc() : blocks_(1, eight_byte_aligned_malloc(sizeof(T)*Tnchunks_per_block)), used_(0) { if (!blocks_[0]) throw std::bad_alloc(); // no msg allowed in bad_alloc ctor }
/** * Construct a resizable stack allocator initially holding the * specified number of bytes. * * @param initial_nbytes Initial number of bytes for the * allocator. Defaults to <code>(1 << 16) = 64KB</code> initial bytes. * @throws std::runtime_error if the underlying malloc is not 8-byte * aligned. */ stack_alloc(size_t initial_nbytes = DEFAULT_INITIAL_NBYTES) : blocks_(1, eight_byte_aligned_malloc(initial_nbytes)), sizes_(1,initial_nbytes), cur_block_(0), cur_block_end_(blocks_[0] + initial_nbytes), next_loc_(blocks_[0]) { if (!blocks_[0]) throw std::bad_alloc(); // no msg allowed in bad_alloc ctor }
/** * Return a newly allocated chunk of memory of the appropriate * size managed by the stack allocator. * * @return A pointer to the allocated memory. */ inline void* alloc() { char *result; if (unlikely(used_ >= Tnchunks_per_block)) { used_ = 0; cur_block_++; } if (unlikely(cur_block_ >= blocks_.size())) { result = eight_byte_aligned_malloc(Tnchunks_per_block*sizeof(T)); if (!result) throw std::bad_alloc(); // no msg allowed in bad_alloc ctor blocks_.push_back(result); } result = blocks_[cur_block_] + sizeof(T)*used_; ++used_; return (void*)result; }
/** * Moves us to the next block of memory, allocating that block * if necessary, and allocates len bytes of memory within that * block. * * @param size_t $len Number of bytes to allocate. * @return A pointer to the allocated memory. */ char* move_to_next_block(size_t len) { char* result; ++cur_block_; // Find the next block (if any) containing at least len bytes. while ((cur_block_ < blocks_.size()) && (sizes_[cur_block_] < len)) ++cur_block_; // Allocate a new block if necessary. if (unlikely(cur_block_ >= blocks_.size())) { // New block should be max(2*size of last block, len) bytes. size_t newsize = sizes_.back() * 2; if (newsize < len) newsize = len; blocks_.push_back(eight_byte_aligned_malloc(newsize)); if (!blocks_.back()) throw std::bad_alloc(); sizes_.push_back(newsize); } result = blocks_[cur_block_]; // Get the object's state back in order. next_loc_ = result + len; cur_block_end_ = result + sizes_[cur_block_]; return result; }