/*
 * Copyright (c) 2017-2020 Arm Limited.
 *
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include "arm_compute/runtime/PoolManager.h"

#include "arm_compute/core/Error.h"
#include "arm_compute/runtime/IMemoryPool.h"

#include <algorithm>
#include <list>

using namespace arm_compute;

PoolManager::PoolManager() : _free_pools(), _occupied_pools(), _sem(), _mtx()
{
}

IMemoryPool *PoolManager::lock_pool()
{
    ARM_COMPUTE_ERROR_ON_MSG(_free_pools.empty() && _occupied_pools.empty(), "Haven't setup any pools!");

    _sem->wait();
    arm_compute::lock_guard<arm_compute::Mutex> lock(_mtx);
    ARM_COMPUTE_ERROR_ON_MSG(_free_pools.empty(), "Empty pool must exist as semaphore has been signalled");
    _occupied_pools.splice(std::begin(_occupied_pools), _free_pools, std::begin(_free_pools));
    return _occupied_pools.front().get();
}

void PoolManager::unlock_pool(IMemoryPool *pool)
{
    ARM_COMPUTE_ERROR_ON_MSG(_free_pools.empty() && _occupied_pools.empty(), "Haven't setup any pools!");

    arm_compute::lock_guard<arm_compute::Mutex> lock(_mtx);
    auto it = std::find_if(std::begin(_occupied_pools), std::end(_occupied_pools),
                           [pool](const std::unique_ptr<IMemoryPool> &pool_it) { return pool_it.get() == pool; });
    ARM_COMPUTE_ERROR_ON_MSG(it == std::end(_occupied_pools), "Pool to be unlocked couldn't be found!");
    _free_pools.splice(std::begin(_free_pools), _occupied_pools, it);
    _sem->signal();
}

void PoolManager::register_pool(std::unique_ptr<IMemoryPool> pool)
{
    arm_compute::lock_guard<arm_compute::Mutex> lock(_mtx);
    ARM_COMPUTE_ERROR_ON_MSG(!_occupied_pools.empty(), "All pools should be free in order to register a new one!");

    // Set pool
    _free_pools.push_front(std::move(pool));

    // Update semaphore
    _sem = std::make_unique<arm_compute::Semaphore>(_free_pools.size());
}

std::unique_ptr<IMemoryPool> PoolManager::release_pool()
{
    arm_compute::lock_guard<arm_compute::Mutex> lock(_mtx);
    ARM_COMPUTE_ERROR_ON_MSG(!_occupied_pools.empty(), "All pools should be free in order to release one!");

    if (!_free_pools.empty())
    {
        std::unique_ptr<IMemoryPool> pool = std::move(_free_pools.front());
        ARM_COMPUTE_ERROR_ON(_free_pools.front() != nullptr);
        _free_pools.pop_front();

        // Update semaphore
        _sem = std::make_unique<arm_compute::Semaphore>(_free_pools.size());

        return pool;
    }

    return nullptr;
}

void PoolManager::clear_pools()
{
    arm_compute::lock_guard<arm_compute::Mutex> lock(_mtx);
    ARM_COMPUTE_ERROR_ON_MSG(!_occupied_pools.empty(), "All pools should be free in order to clear the PoolManager!");
    _free_pools.clear();

    // Update semaphore
    _sem = nullptr;
}

size_t PoolManager::num_pools() const
{
    arm_compute::lock_guard<arm_compute::Mutex> lock(_mtx);

    return _free_pools.size() + _occupied_pools.size();
}
