119 lines
3.4 KiB
C++
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
|