// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef yarn_pool_hpp
#define yarn_pool_hpp

#include "ConditionVariable.hpp"

#include <atomic>
#include <mutex>

namespace yarn {

// PoolPolicy controls whether pool items are constructed and destructed each
// time they are borrowed from and returned to a pool, or whether they persist
// constructed for the lifetime of the pool.
enum class PoolPolicy
{
    // Call the Pool items constructor on borrow(), and destruct the item
    // when the item is returned.
    Reconstruct,

    // Construct and destruct all items once for the lifetime of the Pool.
    // Items will keep their state between loans.
    Preserve,
};

////////////////////////////////////////////////////////////////////////////////
// Pool<T>
////////////////////////////////////////////////////////////////////////////////

// Pool is the abstract base class for BoundedPool<> and UnboundedPool<>.
template <typename T>
class Pool
{
protected:
    struct Item;
    class Storage;

public:
    // A Loan is returned by the pool's borrow() function.
    // Loans track the number of references to the loaned item, and return the
    // item to the pool when the final Loan reference is dropped.
    class Loan
    {
    public:
        inline Loan() = default;
        inline Loan(Item*, const std::shared_ptr<Storage>&);
        inline Loan(const Loan&);
        inline Loan(Loan&&);
        inline ~Loan();
        inline Loan& operator = (const Loan&);
        inline Loan& operator = (Loan&&);
        inline T& operator * ();
        inline T* operator -> () const;
        inline T* get() const;
        void reset();

    private:
        Item *item = nullptr;
        std::shared_ptr<Storage> storage;
    };

protected:
    Pool() = default;

    // The shared storage between the pool and all loans.
    class Storage
    {
    public:
        virtual ~Storage() = default;
        virtual void return_(Item*) = 0;
    };

    // The backing data of a single item in the pool.
    struct Item
    {
        // get() returns a pointer to the item's data.
        inline T* get();

        // construct() calls the constructor on the item's data.
        inline void construct();

        // destruct() calls the destructor on the item's data.
        inline void destruct();

        using Data = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
        Data data;
        std::atomic<int> refcount = {0};
        Item *next = nullptr; // pointer to the next free item in the pool.
    };
};

// Loan<T> is an alias to Pool<T>::Loan.
template <typename T>
using Loan = typename Pool<T>::Loan;

////////////////////////////////////////////////////////////////////////////////
// Pool<T>::Item
////////////////////////////////////////////////////////////////////////////////
template <typename T>
T* Pool<T>::Item::get()
{
    return reinterpret_cast<T*>(&data);
}

template <typename T>
void Pool<T>::Item::construct()
{
    new (&data) T();
}

template <typename T>
void Pool<T>::Item::destruct()
{
    get()->~T();
}

////////////////////////////////////////////////////////////////////////////////
// Pool<T>::Loan
////////////////////////////////////////////////////////////////////////////////
template <typename T>
Pool<T>::Loan::Loan(Item* item, const std::shared_ptr<Storage>& storage) : item(item), storage(storage)
{
    item->refcount++;
}

template <typename T>
Pool<T>::Loan::Loan(const Loan& other) : item(other.item), storage(other.storage)
{
    if (item != nullptr)
    {
        item->refcount++;
    }
}

template <typename T>
Pool<T>::Loan::Loan(Loan&& other) : item(other.item), storage(other.storage)
{
    other.item = nullptr;
    other.storage = nullptr;
}

template <typename T>
Pool<T>::Loan::~Loan()
{
    reset();
}

template <typename T>
void Pool<T>::Loan::reset()
{
    if (item != nullptr)
    {
        auto refs = --item->refcount;
        YARN_ASSERT(refs >= 0, "reset() called on zero-ref pool item");
        if (refs == 0)
        {
            storage->return_(item);
        }
        item = nullptr;
        storage = nullptr;
    }
}

template <typename T>
typename Pool<T>::Loan& Pool<T>::Loan::operator = (const Pool<T>::Loan& rhs)
{
    reset();
    if (rhs.item != nullptr)
    {
        item = rhs.item;
        storage = rhs.storage;
        rhs.item->refcount++;
    }
    return *this;
}

template <typename T>
typename Pool<T>::Loan& Pool<T>::Loan::operator = (Pool<T>::Loan&& rhs)
{
    reset();
    std::swap(item, rhs.item);
    std::swap(storage, rhs.storage);
    return *this;
}

template <typename T>
T& Pool<T>::Loan::operator * () { return *item->get(); }

template <typename T>
T* Pool<T>::Loan::operator -> () const { return item->get(); }

template <typename T>
T* Pool<T>::Loan::get() const { return item->get(); }

////////////////////////////////////////////////////////////////////////////////
// BoundedPool<T, N, POLICY>
////////////////////////////////////////////////////////////////////////////////

// BoundedPool<T, N, POLICY> is a pool of items of type T, with a maximum
// capacity of N items.
// BoundedPool<> is initially populated with N default-constructed items.
// POLICY controls whether pool items are constructed and destructed each
// time they are borrowed from and returned to the pool.
template <typename T, int N, PoolPolicy POLICY = PoolPolicy::Reconstruct>
class BoundedPool : public Pool<T>
{
public:
    using Item = typename Pool<T>::Item;
    using Loan = typename Pool<T>::Loan;

    // borrow() borrows a single item from the pool, blocking until an item is
    // returned if the pool is empty.
    inline Loan borrow() const;

    // borrow() borrows count items from the pool, blocking until there are at
    // least count items in the pool. The function f() is called with each
    // borrowed item.
    // F must be a function with the signature: void(T&&)
    template <typename F>
    inline void borrow(size_t count, const F& f) const;

    // tryBorrow() attempts to borrow a single item from the pool without
    // blocking.
    // The boolean of the returned pair is true on success, or false if the pool
    // is empty.
    inline std::pair<Loan, bool> tryBorrow() const;

private:
    class Storage : public Pool<T>::Storage
    {
    public:
        inline Storage();
        inline ~Storage();
        inline void return_(Item*) override;

        std::mutex mutex;
        ConditionVariable returned;
        Item items[N];
        Item *free = nullptr;
    };
    std::shared_ptr<Storage> storage = std::make_shared<Storage>();
};

template <typename T, int N, PoolPolicy POLICY>
BoundedPool<T, N, POLICY>::Storage::Storage()
{
    for (int i = 0; i < N; i++)
    {
        if (POLICY == PoolPolicy::Preserve)
        {
            items[i].construct();
        }
        items[i].next = this->free;
        this->free = &items[i];
    }
}

template <typename T, int N, PoolPolicy POLICY>
BoundedPool<T, N, POLICY>::Storage::~Storage()
{
    if (POLICY == PoolPolicy::Preserve)
    {
        for (int i = 0; i < N; i++)
        {
            items[i].destruct();
        }
    }
}

template <typename T, int N, PoolPolicy POLICY>
typename BoundedPool<T, N, POLICY>::Loan BoundedPool<T, N, POLICY>::borrow() const
{
    Loan out;
    borrow(1, [&](Loan&& loan) { out = std::move(loan); });
    return out;
}

template <typename T, int N, PoolPolicy POLICY>
template <typename F>
void BoundedPool<T, N, POLICY>::borrow(size_t n, const F& f) const
{
    std::unique_lock<std::mutex> lock(storage->mutex);
    for (size_t i = 0; i < n; i++)
    {
        storage->returned.wait(lock, [&] { return storage->free != nullptr; });
        auto item = storage->free;
        storage->free = storage->free->next;
        if (POLICY == PoolPolicy::Reconstruct)
        {
            item->construct();
        }
        f(std::move(Loan(item, storage)));
    }
}

template <typename T, int N, PoolPolicy POLICY>
std::pair<typename BoundedPool<T, N, POLICY>::Loan, bool> BoundedPool<T, N, POLICY>::tryBorrow() const
{
    std::unique_lock<std::mutex> lock(storage->mutex);
    if (storage->free == nullptr)
    {
        return std::make_pair(Loan(), false);
    }
    auto item = storage->free;
    storage->free = storage->free->next;
    item->pool = this;
    lock.unlock();
    if (POLICY == PoolPolicy::Reconstruct)
    {
        item->construct();
    }
    return std::make_pair(Loan(item, storage), true);
}

template <typename T, int N, PoolPolicy POLICY>
void BoundedPool<T, N, POLICY>::Storage::return_(Item* item)
{
    if (POLICY == PoolPolicy::Reconstruct)
    {
        item->destruct();
    }
    std::unique_lock<std::mutex> lock(mutex);
    item->next = free;
    free = item;
    lock.unlock();
    returned.notify_one();
}

////////////////////////////////////////////////////////////////////////////////
// UnboundedPool
////////////////////////////////////////////////////////////////////////////////

// UnboundedPool<T, POLICY> is a pool of items of type T.
// UnboundedPool<> will automatically allocate more items if the pool becomes
// empty.
// POLICY controls whether pool items are constructed and destructed each
// time they are borrowed from and returned to the pool.
template <typename T, PoolPolicy POLICY = PoolPolicy::Reconstruct>
class UnboundedPool : public Pool<T>
{
public:
    using Item = typename Pool<T>::Item;
    using Loan = typename Pool<T>::Loan;

    // borrow() borrows a single item from the pool, automatically allocating
    // more items if the pool is empty.
    // This function does not block.
    inline Loan borrow() const;

    // borrow() borrows count items from the pool, calling the function f() with
    // each borrowed item.
    // F must be a function with the signature: void(T&&)
    // This function does not block.
    template <typename F>
    inline void borrow(size_t n, const F& f) const;

private:
    class Storage : public Pool<T>::Storage
    {
    public:
        inline ~Storage();
        inline void return_(Item*) override;

        std::mutex mutex;
        std::vector<Item*> items;
        Item *free = nullptr;
    };
    std::shared_ptr<Storage> storage = std::make_shared<Storage>();
};

template <typename T, PoolPolicy POLICY>
UnboundedPool<T, POLICY>::Storage::~Storage()
{
    for (auto item : items)
    {
        if (POLICY == PoolPolicy::Preserve)
        {
            item->destruct();
        }
        delete item;
    }
}

template <typename T, PoolPolicy POLICY>
Loan<T> UnboundedPool<T, POLICY>::borrow() const
{
    Loan out;
    borrow(1, [&] (Loan&& loan) { out = std::move(loan); });
    return out;
}

template <typename T, PoolPolicy POLICY>
template <typename F>
inline void UnboundedPool<T, POLICY>::borrow(size_t n, const F& f) const
{
    std::unique_lock<std::mutex> lock(storage->mutex);
    for (size_t i = 0; i < n; i++)
    {
        if (storage->free == nullptr)
        {
            auto count = std::max<size_t>(storage->items.size(), 32);
            for (size_t i = 0; i < count; i++)
            {
                auto item = new Item();
                if (POLICY == PoolPolicy::Preserve)
                {
                    item->construct();
                }
                storage->items.push_back(item);
                item->next = storage->free;
                storage->free = item;
            }
        }

        auto item = storage->free;
        storage->free = storage->free->next;
        if (POLICY == PoolPolicy::Reconstruct)
        {
            item->construct();
        }
        f(std::move(Loan(item, storage)));
    }
}

template <typename T, PoolPolicy POLICY>
void UnboundedPool<T, POLICY>::Storage::return_(Item* item)
{
    if (POLICY == PoolPolicy::Reconstruct)
    {
        item->destruct();
    }
    std::unique_lock<std::mutex> lock(mutex);
    item->next = free;
    free = item;
    lock.unlock();
}

} // namespace yarn

#endif  // yarn_pool_hpp
