//
// Created by Lenovo on 16.11.2021.
//

#ifndef FIXEDALLOCATOR_FIXED_ALLOCATOR_H
#define FIXEDALLOCATOR_FIXED_ALLOCATOR_H
#pragma once

#include <cstdint>
#include <stack>



template<typename Tp>
class FixedAllocator {
    const std::uint64_t pages;
    PageAllocator page_allocator_;
    std::stack<Tp *> free_chunks;

 public:
    explicit FixedAllocator(uint64_t page_size) :
            page_allocator_(page_size * sizeof(Tp)), pages(page_size) {
        Tp *chunks = static_cast<Tp *>(page_allocator_.Allocate());
        for (uint64_t i = 0; i < pages; i++) {
            free_chunks.push(chunks + i);
        }
    }

    Tp *Allocate() {
        if (free_chunks.empty()) {
            Tp *chunks = static_cast<Tp *>(page_allocator_.Allocate());
            for (uint64_t i = 0; i < pages; i++) {
                free_chunks.push(chunks + i);
            }
        }
        Tp *chunk = free_chunks.top();
        free_chunks.pop();
        return chunk;
    }

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

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

#endif  // FIXEDALLOCATOR_FIXED_ALLOCATOR_H