#pragma once
#include <vector>
#include <unordered_set>
#include <stack>
 
template<typename Tp>

class FixedAllocator {
private:

  PageAllocator page_allocator_;
  unsigned uint64_t page_size_;
  std::stack<Tp*> f_memory;
  std::unordered_set<Tp*> memory;

 public:
    explicit FixedAllocator(std::uint64_t page_size) :
    page_size_(page_size), page_allocator_(page_size * sizeof(Tp)) {}

    Tp* Allocate() {
        if (f_memory.empty()) {
            Tp* f_memory = reinterpret_cast<Tp*>(page_allocator_.Allocate());

            for (unsigned uint64_t i = 0; i < page_size_; i++) {
                f_memory.push(f_memory + i);
            }
        }

        Tp* f_memory = f_memory.top();
        f_memory.pop();

        return f_memory;
    }

    void Deallocate(Tp* p) {
        f_memory.push(p);
    }

    const PageAllocator& InnerAllocator() {
        return page_allocator_;
    }
};