#include "tile/base/internal/background_task_host.h"

#include "tile/base/internal/logging.h"
#include "tile/base/make_unique.h"
#include "tile/base/random.h"

#include "gflags/gflags.h"

#include <set>
#include <utility>

DEFINE_int32(tile_background_task_host_workers_per_node, 4, "");
DEFINE_int32(tile_background_task_host_workers_nice_value, 5, "Determines niceness of background host workers");

namespace tile {
namespace internal {
namespace {}// namespace

BackgroundTaskHost *
BackgroundTaskHost::Instance()
{
    static NeverDestroyedSingleton<BackgroundTaskHost> background_task_host;
    return background_task_host.Get();
}

void
BackgroundTaskHost::Start()
{
    auto logical_cpus = std::thread::hardware_concurrency() / 2;
    if (logical_cpus == 0) {
        logical_cpus = 1;
        TILE_LOG_WARNING("hardware_concurrency() return 0");
    }
    std::vector<int> affinity;

    pools_.resize(1);
    pools_[0] = make_unique<ThreadPool>(logical_cpus, affinity, FLAGS_tile_background_task_host_workers_nice_value);
}

void
BackgroundTaskHost::Stop()
{
    for (auto &&e : pools_) { e->Stop(); }
}

void
BackgroundTaskHost::Join()
{
    for (auto &&e : pools_) { e->Join(); }

    pools_.clear();
}

void
BackgroundTaskHost::Queue(std::function<void()> &&op)
{
    TILE_CHECK_GT(pools_.size(), 0);
    pools_[Random() % pools_.size()]->QueueJob(std::move(op));
}

BackgroundTaskHost::BackgroundTaskHost() = default;

}// namespace internal
}// namespace tile
