#ifndef ALSK_ALSK_EXECUTOR_EXECUTORBASE_H #define ALSK_ALSK_EXECUTOR_EXECUTORBASE_H #include #include #include #include #include #include "tags.h" #include "../impl/tags.h" namespace alsk { namespace exec { struct ExecutorBase { using IsExecutor = tag::Executor; public: struct Info {}; struct RCores { std::vector coresList; RCores() { upTo(std::thread::hardware_concurrency()); } /** * @brief disables repeatability */ void disabled() noexcept { coresList.clear(); } /** * @brief defines possibles cores from min to n by given step * @param n possibly included upper bound, if 0 or 1, disables repeatability * @param min lower bound (at least 2, at most n) * @param step step (at least 1) */ void upTo(std::size_t n, std::size_t min = 2, std::size_t step = 1) { coresList.clear(); if(n < 2) return; std::size_t k = (n-min+step) / step; coresList.resize(k); std::generate_n(std::begin(coresList), n-1, [i=0, &min, &step]() mutable { return (min+step*i++); }); } /** * @brief defines possibles cores from min to n, multiplying by given step * @param n possibly included upper bound, if 0 or 1, disables repeatability * @param min lower bound (at least 2, at most n) * @param step step (at least 2) */ void expUpTo(std::size_t n, std::size_t min = 2, std::size_t step = 2) { coresList.clear(); if(n < 2) return; while(min <= n) { coresList.push_back(min); min *= step; } } /** * @brief defines possibles cores from min to n, multiplying by given step * @param args all cores to support */ template void forValues(Args&&... args) { coresList = {std::forward(args)...}; } }; public: /** * @brief set this variable to the number of allotted cores */ std::size_t cores; /** * @brief this variable allows to configure repeatability */ RCores repeatability; public: ExecutorBase(): cores{std::thread::hardware_concurrency()} {} public: template void config(Impl&) {} template std::size_t contextIdCount(Impl&, std::size_t id) { return id; } template std::size_t contextId(Impl&, std::size_t id) { return id; } template decltype(auto) execute(Impl& impl, BTask& task, Parameters&& parameters, Results&& results, Args&&... args) { return _execute(impl, task, impl.executorInfo, std::forward(parameters), std::forward(results), std::forward(args)...); } template void executeSequential(Impl& impl, BTask& task, Parameters&& parameters, std::size_t n) { return _executeSequential(impl, task, impl.executorInfo, std::forward(parameters), n); } protected: template decltype(auto) _execute(Impl& impl, BTask& task, Info&& info, Parameters&& parameters, Results&& results, Args&&... args) { return Task::execute( impl, task, 0, std::forward(info), std::forward(parameters), std::forward(results), std::forward(args)... ); } template void _executeSequential(Impl& impl, BTask& task, Info const& info, Parameters const& parameters, std::size_t n) { for(std::size_t i = 0; i < n; ++i) Task::execute(impl, task, i, info, parameters, std::tuple<>{}); } }; } } #endif