// // Created by Ivan Arkhipov on 29.04.2018. // #ifndef XOR_LIST_STACKALLOCATOR_H #define XOR_LIST_STACKALLOCATOR_H #include #include #include template class StackAllocator { public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T *pointer; typedef const T *const_pointer; typedef T &reference; typedef const T &const_reference; typedef T value_type; template struct rebind { typedef StackAllocator other; }; StackAllocator() : last_block_(nullptr) {} StackAllocator(const StackAllocator &other) : last_block_(nullptr) {}; StackAllocator(StackAllocator &&other) noexcept : last_block_(nullptr) { other.last_block_ = nullptr; } ~StackAllocator() { for (Block *block = last_block_; block != nullptr;) { Block *prev_block = block->prev_block_; delete block; block = prev_block; } } pointer allocate(size_type n, const void * = nullptr) { if (n > elements_in_block) { throw std::bad_alloc(); } if (!last_block_ || last_block_->end_ + n >= last_block_->block_end_) { last_block_ = new Block(last_block_); } pointer result = last_block_->end_; last_block_->end_ += n; return result; } void deallocate(pointer p, size_type n) { // does nothing } template void construct(U *p, Args &&... args) { ::new((void *) p) U(std::forward(args)...); }; template void destroy(U *p) { p->~U(); } private: struct Block { private: Block() {} public: explicit Block(Block *prev_block = nullptr) { begin_ = reinterpret_cast(::operator new(sizeof(value_type) * elements_in_block)); end_ = begin_; block_end_ = begin_ + elements_in_block; prev_block_ = prev_block; } ~Block() { delete[] begin_; } pointer begin_; pointer end_; pointer block_end_; Block *prev_block_; }; Block *last_block_; }; #endif //XOR_LIST_STACKALLOCATOR_H