thesis version
This commit is contained in:
75
inc/alsk/impl/bone/farm.h
Normal file
75
inc/alsk/impl/bone/farm.h
Normal file
@ -0,0 +1,75 @@
|
||||
#ifndef ALSK_ALSK_IMPL_BONE_FARM_H
|
||||
#define ALSK_ALSK_IMPL_BONE_FARM_H
|
||||
|
||||
#include <cmath>
|
||||
#include <thread>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "../boneimplbase.h"
|
||||
#include "../../skeleton/bone/farm.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
/**
|
||||
* @brief Farm implementation for sequential execution
|
||||
*/
|
||||
template<typename R, typename... Args, typename TTask, typename Executor, typename State>
|
||||
struct Impl<Farm<R(Args...), TTask>, tag::Sequential, Executor, State>:
|
||||
BoneImplBase<Farm<R(Args...), TTask>, tag::Sequential, Executor, State>
|
||||
{
|
||||
using This = Impl;
|
||||
using Task = Execute<typename This::Skeleton::TaskLinks>;
|
||||
|
||||
typename This::Skeleton skeleton;
|
||||
typename This::Executor executor;
|
||||
typename This::StateRef state;
|
||||
|
||||
constexpr Impl() = default;
|
||||
template<typename S>
|
||||
constexpr Impl(S&& skeleton, Executor executor, State& state):
|
||||
skeleton{std::forward<S>(skeleton)},
|
||||
executor{executor},
|
||||
state{state}
|
||||
{}
|
||||
|
||||
constexpr void operator()(Args... args) {
|
||||
executor.template executeSequential<Task>(
|
||||
*this, skeleton.task, std::forward_as_tuple(args...), skeleton.n
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Farm implementation for parallel execution
|
||||
*/
|
||||
template<typename R, typename... Args, typename TTask, typename Executor, typename State>
|
||||
struct Impl<Farm<R(Args...), TTask>, tag::Parallel, Executor, State>:
|
||||
BoneImplBase<Farm<R(Args...), TTask>, tag::Parallel, Executor, State>
|
||||
{
|
||||
using This = Impl;
|
||||
using Task = Execute<typename This::Skeleton::TaskLinks>;
|
||||
|
||||
typename This::Skeleton skeleton;
|
||||
typename This::Executor executor;
|
||||
typename This::StateRef state;
|
||||
|
||||
constexpr Impl() = default;
|
||||
template<typename S>
|
||||
constexpr Impl(S&& skeleton, Executor executor, State& state):
|
||||
skeleton{std::forward<S>(skeleton)},
|
||||
executor{executor},
|
||||
state{state}
|
||||
{}
|
||||
|
||||
constexpr void operator()(Args... args) {
|
||||
executor.template executeParallel<Task>(
|
||||
*this, skeleton.task, std::forward_as_tuple(args...), skeleton.n
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
91
inc/alsk/impl/bone/farmsel.h
Normal file
91
inc/alsk/impl/bone/farmsel.h
Normal file
@ -0,0 +1,91 @@
|
||||
#ifndef ALSK_ALSK_IMPL_BONE_FARMSEL_H
|
||||
#define ALSK_ALSK_IMPL_BONE_FARMSEL_H
|
||||
|
||||
#include <cmath>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "../boneimplbase.h"
|
||||
#include "../../skeleton/bone/farmsel.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
/**
|
||||
* @brief FarmSel implementation for sequential execution
|
||||
*/
|
||||
/*
|
||||
template<typename R, typename... Args, typename... Tasks, typename Executor, typename State>
|
||||
struct Impl<FarmSel<R(Args...), Tasks...>, tag::Sequential, Executor, State>:
|
||||
BoneImplBase<FarmSel<R(Args...), Tasks...>, tag::Sequential, Executor, State>
|
||||
{
|
||||
using This = Impl;
|
||||
using Task = Execute<typename This::Skeleton::TaskLinks>;
|
||||
using Select = Execute<typename This::Skeleton::SelectLinks>;
|
||||
|
||||
typename This::Skeleton skeleton;
|
||||
typename This::Executor executor;
|
||||
typename This::StateRef state;
|
||||
|
||||
constexpr Impl() = default;
|
||||
template<typename S>
|
||||
constexpr Impl(S&& skeleton, Executor executor, State& state):
|
||||
skeleton{std::forward<S>(skeleton)},
|
||||
executor{executor},
|
||||
state{state}
|
||||
{}
|
||||
|
||||
constexpr typename This::Return operator()(Args... args) {
|
||||
using Value = typename This::Return;
|
||||
|
||||
auto tupleP = std::forward_as_tuple(args...);
|
||||
|
||||
Value best{};
|
||||
|
||||
if(skeleton.n)
|
||||
best = executor.template execute<Task>(*this, skeleton.task, tupleP, std::tuple<>{});
|
||||
for(std::size_t i = 1; i < skeleton.n; ++i) {
|
||||
Value current = executor.template execute<Task>(*this, skeleton.task, tupleP, std::tuple<>{});
|
||||
best = executor.template execute<Select>(
|
||||
*this, skeleton.select, tupleP, std::tuple<>{}, std::move(current), std::move(best)
|
||||
);
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief FarmSel implementation for parallel execution
|
||||
*/
|
||||
template<typename R, typename... Args, typename... Tasks, typename Tag, typename Executor, typename State>
|
||||
struct Impl<FarmSel<R(Args...), Tasks...>, Tag, Executor, State>:
|
||||
BoneImplBase<FarmSel<R(Args...), Tasks...>, Tag, Executor, State>
|
||||
{
|
||||
using This = Impl;
|
||||
using Task = Execute<typename This::Skeleton::TaskLinks>;
|
||||
using Select = Execute<typename This::Skeleton::SelectLinks>;
|
||||
|
||||
typename This::Skeleton skeleton;
|
||||
typename This::Executor executor;
|
||||
typename This::StateRef state;
|
||||
|
||||
constexpr Impl() = default;
|
||||
template<typename S>
|
||||
constexpr Impl(S&& skeleton, Executor executor, State& state):
|
||||
skeleton{std::forward<S>(skeleton)},
|
||||
executor{executor},
|
||||
state{state}
|
||||
{}
|
||||
|
||||
constexpr typename This::Return operator()(Args... args) {
|
||||
auto tupleP = std::forward_as_tuple(args...);
|
||||
return executor.template executeParallelAccumulate<typename This::Return, Task, Select>(
|
||||
*this, skeleton.task, skeleton.select, tupleP, skeleton.n
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
57
inc/alsk/impl/bone/itersel.h
Normal file
57
inc/alsk/impl/bone/itersel.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef ALSK_ALSK_IMPL_BONE_ITERSEL_H
|
||||
#define ALSK_ALSK_IMPL_BONE_ITERSEL_H
|
||||
|
||||
#include <cmath>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "../boneimplbase.h"
|
||||
#include "../../skeleton/bone/itersel.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
/**
|
||||
* @brief IterSel implementation for any execution
|
||||
*/
|
||||
template<typename R, typename... Args, typename... Tasks, typename Tag, typename Executor, typename State>
|
||||
struct Impl<IterSel<R(Args...), Tasks...>, Tag, Executor, State>:
|
||||
BoneImplBase<IterSel<R(Args...), Tasks...>, Tag, Executor, State>
|
||||
{
|
||||
using This = Impl;
|
||||
using Task = Execute<typename This::Skeleton::TaskLinks>;
|
||||
using Select = Execute<typename This::Skeleton::SelectLinks>;
|
||||
|
||||
typename This::Skeleton skeleton;
|
||||
typename This::Executor executor;
|
||||
typename This::StateRef state;
|
||||
|
||||
constexpr Impl() = default;
|
||||
template<typename S, typename O>
|
||||
constexpr Impl(S&& skeleton, O&& executor, State& state):
|
||||
skeleton{std::forward<S>(skeleton)},
|
||||
executor{std::forward<O>(executor)},
|
||||
state{state}
|
||||
{}
|
||||
|
||||
// TODO check repeatability with tag::Parallel
|
||||
constexpr typename This::Return operator()(Args... args) {
|
||||
using Value = typename This::Return;
|
||||
|
||||
auto tupleP = std::forward_as_tuple(args...);
|
||||
|
||||
Value best = ArgGet<arg::P<0>>::get(tupleP, std::tuple<>{}, std::tuple<>{});
|
||||
|
||||
for(std::size_t i = 0; i < skeleton.n; ++i) {
|
||||
Value current = executor.template execute<Task>(*this, skeleton.task, tupleP, std::tuple<>{}, best);
|
||||
best = executor.template execute<Select>(
|
||||
*this, skeleton.select, tupleP, std::tuple<>{}, std::move(current), std::move(best)
|
||||
);
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
41
inc/alsk/impl/bone/loop.h
Normal file
41
inc/alsk/impl/bone/loop.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef ALSK_ALSK_IMPL_BONE_LOOP_H
|
||||
#define ALSK_ALSK_IMPL_BONE_LOOP_H
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "../boneimplbase.h"
|
||||
#include "../../skeleton/bone/loop.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
/**
|
||||
* @brief Loop implementation for any execution
|
||||
*/
|
||||
template<typename R, typename... Args, typename Task, typename Tag, typename Executor, typename State>
|
||||
struct Impl<Loop<R(Args...), Task>, Tag, Executor, State>:
|
||||
BoneImplBase<Loop<R(Args...), Task>, Tag, Executor, State>
|
||||
{
|
||||
using This = Impl;
|
||||
using ETask = Execute<typename This::Skeleton::TaskLinks>;
|
||||
|
||||
typename This::Skeleton skeleton;
|
||||
typename This::Executor executor;
|
||||
typename This::StateRef state;
|
||||
|
||||
constexpr Impl() = default;
|
||||
template<typename S, typename O>
|
||||
constexpr Impl(S&& skeleton, O&& executor, State& state):
|
||||
skeleton{std::forward<S>(skeleton)},
|
||||
executor{std::forward<O>(executor)},
|
||||
state{state}
|
||||
{}
|
||||
|
||||
constexpr typename This::Return operator()(Args... args) {
|
||||
for(unsigned int i = 0; i < skeleton.n; ++i)
|
||||
executor.template execute<ETask>(*this, skeleton.task, std::forward_as_tuple(args...), std::tuple<>{});
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
82
inc/alsk/impl/bone/serial.h
Normal file
82
inc/alsk/impl/bone/serial.h
Normal file
@ -0,0 +1,82 @@
|
||||
#ifndef ALSK_ALSK_IMPL_BONE_SERIAL_H
|
||||
#define ALSK_ALSK_IMPL_BONE_SERIAL_H
|
||||
|
||||
#include "../boneimplbase.h"
|
||||
#include "../../skeleton/bone/serial.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
/**
|
||||
* @brief Serial implementation for any execution
|
||||
*/
|
||||
template<typename R, typename... Args, typename... Tasks, typename Tag, typename Executor, typename State>
|
||||
struct Impl<Serial<R(Args...), Tasks...>, Tag, Executor, State>:
|
||||
BoneImplBase<Serial<R(Args...), Tasks...>, Tag, Executor, State>
|
||||
{
|
||||
using This = Impl;
|
||||
using Results = tmp::Repack<std::tuple, tmp::PackReplace<typename This::Skeleton::PackR, void, tmp::Void>>;
|
||||
|
||||
typename This::Skeleton skeleton;
|
||||
typename This::Executor executor;
|
||||
typename This::StateRef state;
|
||||
|
||||
Results results;
|
||||
|
||||
constexpr Impl() = default;
|
||||
template<typename S, typename O>
|
||||
constexpr Impl(S&& skeleton, O&& executor, State& state):
|
||||
skeleton{std::forward<S>(skeleton)},
|
||||
executor{std::forward<O>(executor)},
|
||||
state{state}
|
||||
{}
|
||||
|
||||
// out-of-class definition to silence -Winline
|
||||
~Impl() noexcept;
|
||||
|
||||
// TODO: what happens with rvalue references?
|
||||
constexpr typename This::Return operator()(Args... args) {
|
||||
return serial(std::forward_as_tuple(args...));
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename TupleP>
|
||||
constexpr decltype(auto) serial(TupleP&& p) {
|
||||
serial<0, typename This::Skeleton::Links>(skeleton.tasks, p);
|
||||
return ArgGet<R>::get(std::tuple<>{}, std::move(results), std::tuple<>{});
|
||||
}
|
||||
|
||||
/**
|
||||
* execute
|
||||
*/
|
||||
template<
|
||||
std::size_t I, typename LinksPack, typename TupleTasks,
|
||||
typename TupleP,
|
||||
std::enable_if_t<(I < std::tuple_size<std::decay_t<TupleTasks>>::value)>* = nullptr
|
||||
>
|
||||
constexpr void serial(TupleTasks& tasks, TupleP& p) {
|
||||
using Task = Execute<tmp::PackHead<LinksPack>>;
|
||||
|
||||
std::get<I>(results) = executor.template execute<Task>(
|
||||
*this, std::get<I>(tasks), p, results
|
||||
);
|
||||
serial<I+1, tmp::PackTrail<LinksPack>>(tasks, p);
|
||||
}
|
||||
|
||||
/**
|
||||
* recursion terminaison
|
||||
*/
|
||||
template<
|
||||
std::size_t I, typename LinksPack, typename TupleTasks,
|
||||
typename TupleP,
|
||||
std::enable_if_t<(I == std::tuple_size<std::decay_t<TupleTasks>>::value)>* = nullptr
|
||||
>
|
||||
constexpr void serial(TupleTasks&&, TupleP&&) noexcept {}
|
||||
};
|
||||
|
||||
// out-of-class definition to silence -Winline
|
||||
template<typename R, typename... Args, typename... Tasks, typename Tag, typename Executor, typename State>
|
||||
Impl<Serial<R(Args...), Tasks...>, Tag, Executor, State>::~Impl() noexcept {}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
46
inc/alsk/impl/bone/while.h
Normal file
46
inc/alsk/impl/bone/while.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef ALSK_ALSK_IMPL_BONE_WHILE_H
|
||||
#define ALSK_ALSK_IMPL_BONE_WHILE_H
|
||||
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
#include "../boneimplbase.h"
|
||||
#include "../../skeleton/bone/while.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
/**
|
||||
* @brief While implementation for any execution
|
||||
*/
|
||||
template<typename R, typename... Args, typename... Tasks, typename Tag, typename Executor, typename State>
|
||||
struct Impl<While<R(Args...), Tasks...>, Tag, Executor, State>:
|
||||
BoneImplBase<While<R(Args...), Tasks...>, Tag, Executor, State>
|
||||
{
|
||||
using This = Impl;
|
||||
using Test = Execute<typename This::Skeleton::TestLinks>;
|
||||
using Task = Execute<typename This::Skeleton::TaskLinks>;
|
||||
|
||||
typename This::Skeleton skeleton;
|
||||
typename This::Executor executor;
|
||||
typename This::StateRef state;
|
||||
|
||||
constexpr Impl() = default;
|
||||
template<typename S, typename O>
|
||||
constexpr Impl(S&& skeleton, O&& executor, State& state):
|
||||
skeleton{std::forward<S>(skeleton)},
|
||||
executor{std::forward<O>(executor)},
|
||||
state{state}
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
constexpr typename This::Return operator()(T& a, T const& b) {
|
||||
auto tupleP = std::forward_as_tuple(a, b);
|
||||
|
||||
while(executor.template execute<Test>(*this, skeleton.test, tupleP, std::tuple<>{}))
|
||||
executor.template execute<Task>(*this, skeleton.task, tupleP, std::tuple<>{});
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
40
inc/alsk/impl/boneimplbase.h
Normal file
40
inc/alsk/impl/boneimplbase.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef ALSK_ALSK_IMPL_BONEIMPLBASE_H
|
||||
#define ALSK_ALSK_IMPL_BONEIMPLBASE_H
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "execute.h"
|
||||
#include "tags.h"
|
||||
|
||||
#include "../utility.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
template<typename, typename, typename, typename> struct BoneImplBase;
|
||||
|
||||
template<
|
||||
template<typename...> class Bone,
|
||||
typename R, typename... Args, typename... Tasks,
|
||||
typename Tag_, typename Executor_, typename State_
|
||||
>
|
||||
struct BoneImplBase<Bone<R(Args...), Tasks...>, Tag_, Executor_, State_> {
|
||||
using Signature = R(Args...);
|
||||
using Skeleton = Bone<Signature, Tasks...>;
|
||||
using Tag = Tag_;
|
||||
using Executor = Executor_;
|
||||
using ExecutorInfo = typename std::decay_t<Executor_>::Info;
|
||||
using State = State_;
|
||||
using StateRef = std::reference_wrapper<State>;
|
||||
|
||||
using Return = RealType<R, typename Skeleton::Packs>;
|
||||
|
||||
ExecutorInfo executorInfo;
|
||||
|
||||
constexpr BoneImplBase() noexcept {}
|
||||
|
||||
std::size_t id = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
89
inc/alsk/impl/callable.h
Normal file
89
inc/alsk/impl/callable.h
Normal file
@ -0,0 +1,89 @@
|
||||
#ifndef ALSK_ALSK_IMPL_CALLABLE_H
|
||||
#define ALSK_ALSK_IMPL_CALLABLE_H
|
||||
|
||||
#include "../skeleton/utility.h"
|
||||
#include "../executor/executorstate.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
template<typename Context, typename Executor>
|
||||
struct CallableState {
|
||||
Context context;
|
||||
exec::ExecutorState<Executor> executor;
|
||||
|
||||
// out-of-class definition to silence -Winline
|
||||
~CallableState() noexcept;
|
||||
};
|
||||
|
||||
template<typename Context, typename Executor>
|
||||
CallableState<Context, Executor>::~CallableState() noexcept {}
|
||||
|
||||
template<typename> struct Callable;
|
||||
|
||||
template<
|
||||
template<typename...> class Impl,
|
||||
template<typename...> class Skel, typename R, typename... Operands, typename... Tasks,
|
||||
typename Tag, typename Executor, typename State
|
||||
>
|
||||
struct Callable<Impl<Skel<R(Operands...), Tasks...>, Tag, Executor, State>>:
|
||||
Impl<Skel<R(Operands...), Tasks...>, Tag, Executor, State> {
|
||||
using Skeleton = Skel<R(Operands...), Tasks...>;
|
||||
using Implementation = Impl<Skeleton, Tag, Executor, State>;
|
||||
using ThisType = Callable<Implementation>;
|
||||
|
||||
private:
|
||||
std::size_t _parTasksCount;
|
||||
|
||||
public:
|
||||
State state;
|
||||
|
||||
template<typename... Args, std::enable_if_t<sizeof...(Args) == 2>* = nullptr>
|
||||
constexpr Callable(Args&&... args):
|
||||
Implementation(std::forward<Args>(args)..., state),
|
||||
_parTasksCount{0}
|
||||
{}
|
||||
|
||||
// out-of-class definition to silence -Winline
|
||||
~Callable() noexcept;
|
||||
|
||||
constexpr decltype(auto) operator()(Operands... operands) {
|
||||
update();
|
||||
return Implementation::operator()(operands...);
|
||||
}
|
||||
|
||||
template<typename F, typename T>
|
||||
constexpr decltype(auto) traverse(F&& function, T&& init) {
|
||||
return SkeletonTraversal<Skeleton>::execute(Implementation::skeleton, std::forward<F>(function), std::forward<T>(init));
|
||||
}
|
||||
|
||||
static constexpr tmp::Depth parallelizableLevels() {
|
||||
return skeletonParallelHeight<Skeleton>;
|
||||
}
|
||||
|
||||
std::size_t parallelTasksCount() const { return _parTasksCount; }
|
||||
|
||||
constexpr void update() {
|
||||
auto traverser = [](std::size_t, auto&& skl, auto&&... values) {
|
||||
using Skl = decltype(skl);
|
||||
auto subpar = max(values...);
|
||||
skl.step = subpar;
|
||||
return SkeletonTraitsT<Skl>::parallelizability(std::forward<Skl>(skl)) * subpar;
|
||||
};
|
||||
|
||||
_parTasksCount = traverse(traverser, 1ul);
|
||||
|
||||
ThisType::executor.config(*this);
|
||||
state.context.setup(ThisType::executor.contextIdCount(static_cast<Implementation&>(*this), _parTasksCount));
|
||||
}
|
||||
};
|
||||
|
||||
template<
|
||||
template<typename...> class Impl,
|
||||
template<typename...> class Skel, typename R, typename... Operands, typename... Tasks,
|
||||
typename Tag, typename Executor, typename State
|
||||
>
|
||||
Callable<Impl<Skel<R(Operands...), Tasks...>, Tag, Executor, State>>::~Callable() noexcept {}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
118
inc/alsk/impl/execute.h
Normal file
118
inc/alsk/impl/execute.h
Normal file
@ -0,0 +1,118 @@
|
||||
#ifndef ALSK_ALSK_IMPL_EXECUTE_H
|
||||
#define ALSK_ALSK_IMPL_EXECUTE_H
|
||||
|
||||
#include "../skeleton/utility.h"
|
||||
#include "../executor/traits.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
namespace impl {
|
||||
|
||||
/**
|
||||
* @brief internal implement function
|
||||
* @param executor an instance of the selected executor
|
||||
* @param skeleton an instance of the skeleton to implement
|
||||
* @param state the shared state
|
||||
* @param id the task identifier
|
||||
* @param eInfo information provided by the executor
|
||||
*/
|
||||
template<
|
||||
typename Executor, typename S, typename State, typename CtxId, typename ExecutorInfo,
|
||||
std::enable_if_t<isSkeleton<S>>* = nullptr,
|
||||
std::enable_if_t<isExecutor<Executor>>* = nullptr
|
||||
>
|
||||
auto implement(Executor& executor, S&& skeleton, State&& state, CtxId&& id, ExecutorInfo&& eInfo) {
|
||||
using ImplType = Impl<std::decay_t<S>, typename Executor::Tag, Executor&, std::remove_reference_t<State>>;
|
||||
|
||||
auto impl = ImplType{std::forward<S>(skeleton), executor, std::forward<State>(state)};
|
||||
impl.id = std::forward<CtxId>(id);
|
||||
impl.executorInfo = std::forward<ExecutorInfo>(eInfo);
|
||||
return impl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief internal implement function for end muscles
|
||||
* @param executor ignored
|
||||
* @param value a muscle
|
||||
* @param state ignored
|
||||
* @param id ignored
|
||||
* @param eInfo ignored
|
||||
*/
|
||||
template<typename Executor, typename T, typename State, typename CtxId, typename ExecutorInfo,
|
||||
std::enable_if_t<not isSkeleton<T>>* = nullptr,
|
||||
std::enable_if_t<isExecutor<Executor>>* = nullptr
|
||||
>
|
||||
decltype(auto) implement(Executor&, T&& value, State&&, CtxId&&, ExecutorInfo&&) {
|
||||
return std::forward<T>(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*/
|
||||
namespace impl {
|
||||
|
||||
template<typename> struct Execute {};
|
||||
|
||||
template<typename Ret, typename... Ps>
|
||||
struct Execute<Ret(Ps...)> {
|
||||
template<
|
||||
typename Impl, typename Task, typename CtxId, typename ExecutorInfo,
|
||||
typename P, typename R, typename... Args
|
||||
>
|
||||
static decltype(auto) execute(Impl& impl, Task&& task, CtxId&& cid, ExecutorInfo&& eInfo, P&& p, R&& r, Args&&... args) {
|
||||
auto id = impl.id + std::forward<CtxId>(cid) * impl.skeleton.step;
|
||||
typename Impl::State& state = impl.state;
|
||||
|
||||
return executeF(
|
||||
impl::implement(impl.executor, std::forward<Task>(task), state, id, std::forward<ExecutorInfo>(eInfo)),
|
||||
std::forward<P>(p), std::forward<R>(r),
|
||||
state.context.args(impl.executor.contextId(impl, id)),
|
||||
std::forward<Args>(args)...
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
template<
|
||||
typename F, typename P, typename R, typename C, typename... Args,
|
||||
typename Result = tmp::invoke_result_t<
|
||||
std::decay_t<F>,
|
||||
Args...,
|
||||
ArgType<Ps, arg::Placeholders<P, R, C>>...
|
||||
>,
|
||||
std::enable_if_t<not std::is_same<Result, void>::value>* = nullptr
|
||||
>
|
||||
static Result executeF(F&& f, P&& p, R&& r, C&& c, Args&&... args) {
|
||||
return std::forward<F>(f)(
|
||||
std::forward<Args>(args)...,
|
||||
ArgGet<Ps>::get(std::forward<P>(p), std::forward<R>(r), std::forward<C>(c))...
|
||||
);
|
||||
}
|
||||
|
||||
template<
|
||||
typename F, typename P, typename R, typename C, typename... Args,
|
||||
typename Result = tmp::invoke_result_t<
|
||||
std::decay_t<F>,
|
||||
Args...,
|
||||
ArgType<Ps, arg::Placeholders<P, R, C>>...
|
||||
>,
|
||||
std::enable_if_t<std::is_same<Result, void>::value>* = nullptr
|
||||
>
|
||||
static auto executeF(F&& f, P&& p, R&& r, C&& c, Args&&... args) {
|
||||
std::forward<F>(f)(
|
||||
std::forward<Args>(args)...,
|
||||
ArgGet<Ps>::get(std::forward<P>(p), std::forward<R>(r), std::forward<C>(c))...
|
||||
);
|
||||
return tmp::Void{};
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename Signature>
|
||||
using Execute = impl::Execute<ArgFilter<Signature>>;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
13
inc/alsk/impl/impl.h
Normal file
13
inc/alsk/impl/impl.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef ALSK_ALSK_IMPL_IMPL_H
|
||||
#define ALSK_ALSK_IMPL_IMPL_H
|
||||
|
||||
#include "bone/farm.h"
|
||||
#include "bone/farmsel.h"
|
||||
#include "bone/itersel.h"
|
||||
#include "bone/loop.h"
|
||||
#include "bone/serial.h"
|
||||
#include "bone/while.h"
|
||||
|
||||
#include "implement.h"
|
||||
|
||||
#endif
|
57
inc/alsk/impl/implement.h
Normal file
57
inc/alsk/impl/implement.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef ALSK_ALSK_IMPL_IMPLEMENT_H
|
||||
#define ALSK_ALSK_IMPL_IMPLEMENT_H
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "callable.h"
|
||||
|
||||
#include "../context/context.h"
|
||||
#include "../executor/traits.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
/**
|
||||
* @brief implement a skeleton
|
||||
* @param TExecutor the executor template
|
||||
* @param Skeleton the skeleton type
|
||||
* @param Context [optional] the type of the context
|
||||
*
|
||||
* @return a callable
|
||||
*/
|
||||
template<template<typename> class TExecutor, typename Skeleton,
|
||||
typename Context = DefaultContext,
|
||||
std::enable_if_t<isSkeleton<Skeleton>>* = nullptr,
|
||||
std::enable_if_t<isExecutor<TExecutor<Skeleton>>>* = nullptr
|
||||
>
|
||||
auto implement() {
|
||||
using Executor = TExecutor<Skeleton>;
|
||||
using State = CallableState<Context, Executor>;
|
||||
using ImplType = Impl<Skeleton, typename Executor::Tag, Executor, State>;
|
||||
|
||||
return Callable<ImplType>(Skeleton{}, Executor{});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief implement a skeleton
|
||||
* @param executor an instance of the executor
|
||||
* @param skeleton an instance of the skeleton to implement
|
||||
* @param Context [optional] the type of the context
|
||||
*
|
||||
* @return a callable
|
||||
*/
|
||||
template<typename Context = DefaultContext,
|
||||
typename Executor, typename S,
|
||||
std::enable_if_t<isSkeleton<S>>* = nullptr,
|
||||
std::enable_if_t<isExecutor<Executor>>* = nullptr
|
||||
>
|
||||
auto implement(Executor&& executor, S&& skeleton) {
|
||||
using ExecutorT = std::decay_t<Executor>;
|
||||
using State = CallableState<Context, ExecutorT>;
|
||||
using ImplType = Impl<std::decay_t<S>, typename ExecutorT::Tag, ExecutorT, State>;
|
||||
|
||||
return Callable<ImplType>(std::forward<S>(skeleton), std::forward<Executor>(executor));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
13
inc/alsk/impl/tags.h
Normal file
13
inc/alsk/impl/tags.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef ALSK_ALSK_IMPL_TAGS_H
|
||||
#define ALSK_ALSK_IMPL_TAGS_H
|
||||
|
||||
namespace alsk {
|
||||
namespace tag {
|
||||
|
||||
struct Sequential {};
|
||||
struct Parallel {};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user