/*
 * 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/ISimpleLifetimeManager.h"

#include "arm_compute/core/Error.h"
#include "arm_compute/runtime/IAllocator.h"
#include "arm_compute/runtime/IMemory.h"
#include "arm_compute/runtime/IMemoryGroup.h"
#include "arm_compute/runtime/IMemoryPool.h"

#include <algorithm>
#include <cmath>
#include <map>
#include <vector>

namespace arm_compute
{
ISimpleLifetimeManager::ISimpleLifetimeManager()
    : _active_group(nullptr), _active_elements(), _free_blobs(), _occupied_blobs(), _finalized_groups()
{
}

void ISimpleLifetimeManager::register_group(IMemoryGroup *group)
{
    if(_active_group == nullptr)
    {
        ARM_COMPUTE_ERROR_ON(group == nullptr);
        _active_group = group;
    }
}

bool ISimpleLifetimeManager::release_group(IMemoryGroup *group)
{
    if(group == nullptr)
    {
        return false;
    }
    const bool status = bool(_finalized_groups.erase(group));
    if(status)
    {
        group->mappings().clear();
    }
    return status;
}

void ISimpleLifetimeManager::start_lifetime(void *obj)
{
    ARM_COMPUTE_ERROR_ON(obj == nullptr);
    ARM_COMPUTE_ERROR_ON_MSG(_active_elements.find(obj) != std::end(_active_elements), "Memory object is already registered!");

    // Check if there is a free blob
    if(_free_blobs.empty())
    {
        _occupied_blobs.emplace_front(Blob{ obj, 0, 0, { obj } });
    }
    else
    {
        _occupied_blobs.splice(std::begin(_occupied_blobs), _free_blobs, std::begin(_free_blobs));
        _occupied_blobs.front().id = obj;
    }

    // Insert object in groups and mark its finalized state to false
    _active_elements.insert(std::make_pair(obj, obj));
}

void ISimpleLifetimeManager::end_lifetime(void *obj, IMemory &obj_memory, size_t size, size_t alignment)
{
    ARM_COMPUTE_ERROR_ON(obj == nullptr);

    // Find object
    auto active_object_it = _active_elements.find(obj);
    ARM_COMPUTE_ERROR_ON(active_object_it == std::end(_active_elements));

    // Update object fields and mark object as complete
    Element &el  = active_object_it->second;
    el.handle    = &obj_memory;
    el.size      = size;
    el.alignment = alignment;
    el.status    = true;

    // Find object in the occupied lists
    auto occupied_blob_it = std::find_if(std::begin(_occupied_blobs), std::end(_occupied_blobs), [&obj](const Blob & b)
    {
        return obj == b.id;
    });
    ARM_COMPUTE_ERROR_ON(occupied_blob_it == std::end(_occupied_blobs));

    // Update occupied blob and return as free
    occupied_blob_it->bound_elements.insert(obj);
    occupied_blob_it->max_size      = std::max(occupied_blob_it->max_size, size);
    occupied_blob_it->max_alignment = std::max(occupied_blob_it->max_alignment, alignment);
    occupied_blob_it->id            = nullptr;
    _free_blobs.splice(std::begin(_free_blobs), _occupied_blobs, occupied_blob_it);

    // Check if all objects are finalized and reset active group
    if(are_all_finalized())
    {
        ARM_COMPUTE_ERROR_ON(!_occupied_blobs.empty());

        // Update blobs and group mappings
        update_blobs_and_mappings();

        // Update finalized groups
        _finalized_groups[_active_group].insert(std::begin(_active_elements), std::end(_active_elements));

        // Reset state
        _active_elements.clear();
        _active_group = nullptr;
        _free_blobs.clear();
    }
}

bool ISimpleLifetimeManager::are_all_finalized() const
{
    return !std::any_of(std::begin(_active_elements), std::end(_active_elements), [](const std::pair<void *, Element> &e)
    {
        return !e.second.status;
    });
}
} // namespace arm_compute
