rosa/inc/alsk/executor/executorbase.h

126 lines
3.6 KiB
C
Raw Permalink Normal View History

2021-05-10 16:14:24 +00:00
#ifndef ALSK_ALSK_EXECUTOR_EXECUTORBASE_H
#define ALSK_ALSK_EXECUTOR_EXECUTORBASE_H
#include <algorithm>
#include <thread>
#include <tuple>
#include <utility>
#include <vector>
#include "tags.h"
#include "../impl/tags.h"
namespace alsk {
namespace exec {
struct ExecutorBase {
using IsExecutor = tag::Executor;
public:
struct Info {};
struct RCores {
std::vector<std::size_t> 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<typename... Args>
void forValues(Args&&... args) {
coresList = {std::forward<Args>(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<typename Impl>
void config(Impl&) {}
template<typename Impl>
std::size_t contextIdCount(Impl&, std::size_t id) { return id; }
template<typename Impl>
std::size_t contextId(Impl&, std::size_t id) { return id; }
template<typename Task, typename Impl, typename BTask, typename Parameters, typename Results, typename... Args>
decltype(auto) execute(Impl& impl, BTask& task, Parameters&& parameters, Results&& results, Args&&... args) {
return _execute<Task>(impl, task, impl.executorInfo, std::forward<Parameters>(parameters), std::forward<Results>(results),
std::forward<Args>(args)...);
}
template<typename Task, typename Impl, typename BTask, typename Parameters>
void executeSequential(Impl& impl, BTask& task, Parameters&& parameters, std::size_t n) {
return _executeSequential<Task>(impl, task, impl.executorInfo, std::forward<Parameters>(parameters), n);
}
protected:
template<typename Task, typename Impl, typename BTask, typename Info, typename Parameters, typename Results, typename... Args>
decltype(auto) _execute(Impl& impl, BTask& task, Info&& info, Parameters&& parameters, Results&& results, Args&&... args) {
return Task::execute(
impl, task, 0, std::forward<Info>(info), std::forward<Parameters>(parameters), std::forward<Results>(results),
std::forward<Args>(args)...
);
}
template<typename Task, typename Impl, typename BTask, typename Info, typename Parameters>
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