1 #ifndef STAN_MATH_MEMORY_STACK_ALLOC_HPP 2 #define STAN_MATH_MEMORY_STACK_ALLOC_HPP 30 return (reinterpret_cast<uintptr_t>(ptr) % bytes_aligned) == 0U;
34 const size_t DEFAULT_INITIAL_NBYTES = 1 << 16;
38 inline char* eight_byte_aligned_malloc(
size_t size) {
39 char* ptr =
static_cast<char*
>(malloc(size));
43 s <<
"invalid alignment to 8 bytes, ptr=" 44 <<
reinterpret_cast<uintptr_t
>(ptr)
46 throw std::runtime_error(s.str());
73 std::vector<char*> blocks_;
75 std::vector<size_t> sizes_;
81 std::vector<size_t> nested_cur_blocks_;
82 std::vector<char*> nested_next_locs_;
83 std::vector<char*> nested_cur_block_ends_;
93 char* move_to_next_block(
size_t len) {
97 while ((cur_block_ < blocks_.size()) && (sizes_[cur_block_] < len))
100 if (
unlikely(cur_block_ >= blocks_.size())) {
102 size_t newsize = sizes_.back() * 2;
105 blocks_.push_back(eight_byte_aligned_malloc(newsize));
107 throw std::bad_alloc();
108 sizes_.push_back(newsize);
110 result = blocks_[cur_block_];
112 next_loc_ = result + len;
113 cur_block_end_ = result + sizes_[cur_block_];
127 explicit stack_alloc(
size_t initial_nbytes = DEFAULT_INITIAL_NBYTES) :
128 blocks_(1, eight_byte_aligned_malloc(initial_nbytes)),
129 sizes_(1, initial_nbytes),
131 cur_block_end_(blocks_[0] + initial_nbytes),
132 next_loc_(blocks_[0]) {
134 throw std::bad_alloc();
145 for (
size_t i = 0; i < blocks_.size(); ++i)
164 char* result = next_loc_;
167 if (
unlikely(next_loc_ >= cur_block_end_))
168 result = move_to_next_block(len);
169 return reinterpret_cast<void*
>(result);
180 template <
typename T>
183 return static_cast<T*
>(
alloc(n *
sizeof(T)));
194 next_loc_ = blocks_[0];
195 cur_block_end_ = next_loc_ + sizes_[0];
203 nested_cur_blocks_.push_back(cur_block_);
204 nested_next_locs_.push_back(next_loc_);
205 nested_cur_block_ends_.push_back(cur_block_end_);
212 if (
unlikely(nested_cur_blocks_.empty()))
215 cur_block_ = nested_cur_blocks_.back();
216 nested_cur_blocks_.pop_back();
218 next_loc_ = nested_next_locs_.back();
219 nested_next_locs_.pop_back();
221 cur_block_end_ = nested_cur_block_ends_.back();
222 nested_cur_block_ends_.pop_back();
232 for (
size_t i = 1; i < blocks_.size(); ++i)
252 for (
size_t i = 0; i <= cur_block_; ++i) {
267 for (
size_t i = 0; i < cur_block_; ++i)
268 if (ptr >= blocks_[i] && ptr < blocks_[i] + sizes_[i])
270 if (ptr >= blocks_[cur_block_] && ptr < next_loc_)
fvar< T > sum(const std::vector< fvar< T > > &m)
Return the sum of the entries of the specified standard vector.
size_t bytes_allocated() const
Return number of bytes allocated to this instance by the heap.
~stack_alloc()
Destroy this memory allocator.
void recover_nested()
recover memory back to the last start_nested call.
void free_all()
Free all memory used by the stack allocator other than the initial block allocation back to the syste...
void recover_all()
Recover all the memory used by the stack allocator.
bool in_stack(const void *ptr) const
Indicates whether the memory in the pointer is in the stack.
T * alloc_array(size_t n)
Allocate an array on the arena of the specified size to hold values of the specified template paramet...
int size(const std::vector< T > &x)
Return the size of the specified standard vector.
void start_nested()
Store current positions before doing nested operation so can recover back to start.
bool is_aligned(T *ptr, unsigned int bytes_aligned)
Return true if the specified pointer is aligned on the number of bytes.
stack_alloc(size_t initial_nbytes=DEFAULT_INITIAL_NBYTES)
Construct a resizable stack allocator initially holding the specified number of bytes.
An instance of this class provides a memory pool through which blocks of raw memory may be allocated ...
void * alloc(size_t len)
Return a newly allocated block of memory of the appropriate size managed by the stack allocator...