alsk/src/alsk/impl/execute.h

119 lines
3.4 KiB
C++

#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