ROSE  0.9.9.139
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://github.com/matzke1/sawyer.
4 
5 
6 
7 
8 #ifndef SAWYER_STACK_ALLOCATOR
9 #define SAWYER_STACK_ALLOCATOR
10 
11 namespace Sawyer {
12 
18 template<typename T>
20 public:
21  typedef T Value;
23 private:
24  const size_t elmtsPerBlock_; // elements per large block of memory requested
25  std::list<T*> blocks_; // front() is the most recent block from which an element is allocated
26  size_t available_; // number of elements available in most recent block
27  std::list<T*> freeBlocks_; // blocks that aren't being used currently
28 
29 public:
30  explicit StackAllocator(size_t elmtsPerBlock)
31  : elmtsPerBlock_(elmtsPerBlock), available_(0) {}
32 
33  ~StackAllocator() {
34  prune();
35  BOOST_FOREACH (T *ptr, blocks_)
36  delete[] ptr;
37  blocks_.clear();
38  available_ = 0;
39  }
40 
42  void prune() {
43  BOOST_FOREACH (T *ptr, freeBlocks_)
44  delete[] ptr;
45  freeBlocks_.clear();
46  }
47 
52  T* reserve(size_t nElmts) {
53  if (nElmts > available_) {
54  ASSERT_require(nElmts <= elmtsPerBlock_);
55  allocateBlock();
56  }
57  return blocks_.front() + (elmtsPerBlock_ - available_);
58  }
59 
62  T* allocNext() {
63  if (0 == available_)
64  allocateBlock();
65  return blocks_.front() + (elmtsPerBlock_ - available_--);
66  }
67 
71  void revert(T *ptr) {
72  ASSERT_not_null(ptr);
73  while (!blocks_.empty() && (ptr < blocks_.front() || ptr >= blocks_.front() + elmtsPerBlock_))
74  freeBlock();
75  ASSERT_always_forbid2(blocks_.empty(), "bad address or previously reverted");
76  available_ = elmtsPerBlock_ - (ptr - blocks_.front());
77  }
78 
79 private:
80  void allocateBlock() {
81  if (freeBlocks_.empty()) {
82  blocks_.insert(blocks_.begin(), new T[elmtsPerBlock_]);
83  } else {
84  blocks_.insert(blocks_.begin(), freeBlocks_.front());
85  freeBlocks_.erase(freeBlocks_.begin());
86  }
87  available_ = elmtsPerBlock_;
88  }
89 
90  void freeBlock() {
91  ASSERT_forbid(blocks_.empty());
92  freeBlocks_.insert(freeBlocks_.begin(), blocks_.front());
93  blocks_.erase(blocks_.begin());
94  available_ = 0;
95  }
96 };
97 
98 } // namespace
99 
100 #endif
void clear(SharedPointer< T > &ptr)
Make pointer point to nothing.
T * reserve(size_t nElmts)
Reserve space for objects.
T * allocNext()
Allocate one element.
void revert(T *ptr)
Free all elements back to the specified element.
Name space for the entire library.
Definition: Access.h:11
void prune()
Free unused large blocks.
Stack-like allocator.
T Value
Type of values being allocated.