#pragma once

#include <string>
#include <vector>

template<typename Tp>
class FixedAllocator {
 public:
  explicit FixedAllocator(std::uint64_t page_size) : page_size_(page_size),
  page_allocator_(PageAllocator(sizeof(Tp) * page_size_)) {
  }

  Tp *Allocate() {
    Tp *page;
    if (free_.size() == 0) {
      page = static_cast<Tp *>(page_allocator_.Allocate());

      for (std::uint64_t i = 0; i < page_size_; i++) {
        free_.push_back(page+i);
      }
    }
    page = free_.front();
    free_.erase(free_.begin());
    return page;
  }

  void Deallocate(Tp *p) {
    free_.push_back(p);
  }

  const PageAllocator &InnerAllocator() const noexcept {
    return page_allocator_;
  }
  
 private:
  PageAllocator page_allocator_;
  const std::uint64_t page_size_;
  std::vector<Tp *> free_;
};