#include <cstdint>
#include <stack>

template<typename Tp>
class FixedAllocator {
 private:
  PageAllocator *page_allocator_;
  std::stack<Tp*> free_pull;
  std::uint64_t page_size_;
 public:
  explicit FixedAllocator(std::uint64_t page_size): page_size_(page_size) {
    page_allocator_ = new PageAllocator(page_size*sizeof(Tp));
  }
  Tp* Allocate() {
    if (!free_pull.empty()) {
      Tp* answer = free_pull.top();
      free_pull.pop();
      return answer;
    } else {
      Tp* newPage = reinterpret_cast<Tp*>(page_allocator_->Allocate());
      for (std::uint64_t i=0; i < page_size_; i++) {
        free_pull.push(newPage+i);
      }
      Tp* answer = free_pull.top();
      free_pull.pop();
      return answer;
    }
  }
  void Deallocate(Tp* p) {
    free_pull.push(p);
  }
  [[nodiscard]] const PageAllocator& InnerAllocator() const noexcept {
    return *page_allocator_;
  }
};