ROSE 0.11.145.147
StackAllocator.h
1// WARNING: Changes to this file must be contributed back to Sawyer or else they will
2// be clobbered by the next update from Sawyer. The Sawyer repository is at
3// https://gitlab.com/charger7534/sawyer.git.
4
5
6
7
8#ifndef SAWYER_STACK_ALLOCATOR
9#define SAWYER_STACK_ALLOCATOR
10
11#include <Sawyer/Sawyer.h>
12
13namespace Sawyer {
14
20template<typename T>
22public:
23 typedef T Value;
25private:
26 const size_t elmtsPerBlock_; // elements per large block of memory requested
27 std::list<T*> blocks_; // front() is the most recent block from which an element is allocated
28 size_t available_; // number of elements available in most recent block
29 std::list<T*> freeBlocks_; // blocks that aren't being used currently
30
31public:
32 explicit StackAllocator(size_t elmtsPerBlock)
33 : elmtsPerBlock_(elmtsPerBlock), available_(0) {}
34
36 prune();
37 BOOST_FOREACH (T *ptr, blocks_)
38 delete[] ptr;
39 blocks_.clear();
40 available_ = 0;
41 }
42
44 void prune() {
45 BOOST_FOREACH (T *ptr, freeBlocks_)
46 delete[] ptr;
47 freeBlocks_.clear();
48 }
49
54 T* reserve(size_t nElmts) {
55 if (nElmts > available_) {
56 ASSERT_require(nElmts <= elmtsPerBlock_);
57 allocateBlock();
58 }
59 return blocks_.front() + (elmtsPerBlock_ - available_);
60 }
61
64 T* allocNext() {
65 if (0 == available_)
66 allocateBlock();
67 return blocks_.front() + (elmtsPerBlock_ - available_--);
68 }
69
73 void revert(T *ptr) {
74 ASSERT_not_null(ptr);
75 while (!blocks_.empty() && (ptr < blocks_.front() || ptr >= blocks_.front() + elmtsPerBlock_))
76 freeBlock();
77 ASSERT_always_forbid2(blocks_.empty(), "bad address or previously reverted");
78 available_ = elmtsPerBlock_ - (ptr - blocks_.front());
79 }
80
81private:
82 void allocateBlock() {
83 if (freeBlocks_.empty()) {
84 blocks_.insert(blocks_.begin(), new T[elmtsPerBlock_]);
85 } else {
86 blocks_.insert(blocks_.begin(), freeBlocks_.front());
87 freeBlocks_.erase(freeBlocks_.begin());
88 }
89 available_ = elmtsPerBlock_;
90 }
91
92 void freeBlock() {
93 ASSERT_forbid(blocks_.empty());
94 freeBlocks_.insert(freeBlocks_.begin(), blocks_.front());
95 blocks_.erase(blocks_.begin());
96 available_ = 0;
97 }
98};
99
100} // namespace
101
102#endif
Stack-like allocator.
T * allocNext()
Allocate one element.
T Value
Type of values being allocated.
void revert(T *ptr)
Free all elements back to the specified element.
void prune()
Free unused large blocks.
T * reserve(size_t nElmts)
Reserve space for objects.
Sawyer support library.