
#ifndef PLS_INVOKE_PARALLEL_IMPL_H
#define PLS_INVOKE_PARALLEL_IMPL_H

#include "pls/internal/scheduling/task.h"
#include "pls/internal/scheduling/lambda_task.h"
#include "pls/internal/scheduling/scheduler.h"
#include "pls/internal/scheduling/thread_state.h"

namespace pls {
namespace algorithm {

template<typename Function1, typename Function2>
void invoke(Function1 &&function1, Function2 &&function2) {
  using namespace ::pls::internal::scheduling;

  using task_1_t = lambda_task_by_value<Function1>;
  using task_2_t = lambda_task_by_value<Function2>;

  scheduler::spawn_child<task_2_t>(std::forward<Function2>(function2));
  scheduler::spawn_child_and_wait<task_1_t>(std::forward<Function1>(function1));
}

template<typename Function1, typename Function2, typename Function3>
void invoke(Function1 &&function1, Function2 &&function2, Function3 &&function3) {
  using namespace ::pls::internal::scheduling;

  using task_1_t = lambda_task_by_value<Function1>;
  using task_2_t = lambda_task_by_value<Function2>;
  using task_3_t = lambda_task_by_value<Function3>;

  scheduler::spawn_child<task_3_t>(std::forward<Function3>(function3));
  scheduler::spawn_child<task_2_t>(std::forward<Function2>(function2));
  scheduler::spawn_child_and_wait<task_1_t>(std::forward<Function1>(function1));
}

}
}

#endif //PLS_INVOKE_PARALLEL_IMPL_H
