21 #include <type_traits>
45 : std::runtime_error(message)
102 struct root_type : std::integral_constant<transwarp::task_type, transwarp::task_type::root> {};
106 struct accept_type : std::integral_constant<transwarp::task_type, transwarp::task_type::accept> {};
110 struct accept_any_type : std::integral_constant<transwarp::task_type, transwarp::task_type::accept_any> {};
114 struct consume_type : std::integral_constant<transwarp::task_type, transwarp::task_type::consume> {};
118 struct consume_any_type : std::integral_constant<transwarp::task_type, transwarp::task_type::consume_any> {};
122 struct wait_type : std::integral_constant<transwarp::task_type, transwarp::task_type::wait> {};
126 struct wait_any_type : std::integral_constant<transwarp::task_type, transwarp::task_type::wait_any> {};
152 node& operator=(
const node&) =
delete;
172 const std::shared_ptr<std::string>&
get_name() const noexcept {
182 const std::vector<std::shared_ptr<node>>&
get_parents() const noexcept {
198 return canceled_.load();
205 std::size_t level_ = 0;
207 std::shared_ptr<std::string> name_;
208 std::shared_ptr<std::string> executor_;
209 std::vector<std::shared_ptr<node>> parents_;
210 std::size_t priority_ = 0;
211 std::shared_ptr<void> custom_data_;
212 std::atomic_bool canceled_{
false};
221 s +=
"<" + *name +
">" + seperator;
224 s +=
" id=" + std::to_string(node.
get_id());
225 s +=
" lev=" + std::to_string(node.
get_level());
228 s += seperator +
"<" + *exec +
">";
239 edge(std::shared_ptr<transwarp::node> parent, std::shared_ptr<transwarp::node> child) noexcept
240 : parent_(std::move(parent)), child_(std::move(child))
245 edge& operator=(
const edge&) =
default;
250 const std::shared_ptr<transwarp::node>&
get_parent() const noexcept {
255 const std::shared_ptr<transwarp::node>&
get_child() const noexcept {
260 std::shared_ptr<transwarp::node> parent_;
261 std::shared_ptr<transwarp::node> child_;
271 inline std::string
to_string(
const std::vector<transwarp::edge>& graph,
const std::string& separator=
"\n") {
272 std::string dot =
"digraph {" + separator;
273 for (
const auto&
edge : graph) {
287 virtual std::string
get_name()
const = 0;
293 virtual void execute(
const std::function<
void()>&
functor,
const std::shared_ptr<transwarp::node>&
node) = 0;
328 virtual ~
itask() =
default;
330 virtual void set_executor(std::shared_ptr<transwarp::executor>
executor) = 0;
331 virtual void set_executor_all(std::shared_ptr<transwarp::executor> executor) = 0;
332 virtual void remove_executor() = 0;
333 virtual void remove_executor_all() = 0;
334 virtual void set_priority(std::size_t priority) = 0;
335 virtual void set_priority_all(std::size_t priority) = 0;
336 virtual void reset_priority() = 0;
337 virtual void reset_priority_all() = 0;
338 virtual void set_custom_data(std::shared_ptr<void> custom_data) = 0;
339 virtual void set_custom_data_all(std::shared_ptr<void> custom_data) = 0;
340 virtual void remove_custom_data() = 0;
341 virtual void remove_custom_data_all() = 0;
342 virtual const std::shared_ptr<transwarp::node>& get_node()
const noexcept = 0;
343 virtual void add_listener(std::shared_ptr<transwarp::listener>
listener) = 0;
344 virtual void add_listener(
transwarp::event_type event, std::shared_ptr<transwarp::listener> listener) = 0;
345 virtual void remove_listener(
const std::shared_ptr<transwarp::listener>& listener) = 0;
346 virtual void remove_listener(
transwarp::event_type event,
const std::shared_ptr<transwarp::listener>& listener) = 0;
348 virtual void remove_listeners() = 0;
349 virtual void schedule() = 0;
351 virtual void schedule(
bool reset) = 0;
353 virtual void schedule_all() = 0;
355 virtual void schedule_all(
bool reset_all) = 0;
361 virtual void set_exception(std::exception_ptr exception) = 0;
362 virtual bool was_scheduled()
const noexcept = 0;
363 virtual void wait()
const = 0;
364 virtual bool is_ready()
const = 0;
365 virtual bool has_result()
const = 0;
366 virtual void reset() = 0;
367 virtual void reset_all() = 0;
368 virtual void cancel(
bool enabled) noexcept = 0;
369 virtual void cancel_all(
bool enabled) noexcept = 0;
370 virtual std::vector<transwarp::edge> get_graph()
const = 0;
381 virtual void visit_depth(
const std::function<
void(
itask&)>& visitor) = 0;
382 virtual void unvisit() noexcept = 0;
383 virtual void set_node_id(std::size_t
id) noexcept = 0;
390 using type =
typename std::remove_const<typename std::remove_reference<T>::type>::type;
397 using type =
typename std::result_of<decltype(&std::shared_future<T>::get)(std::shared_future<T>)>::type;
402 template<
typename ResultType>
405 using result_type = ResultType;
407 virtual ~
task() =
default;
409 virtual void set_value(
const typename transwarp::decay<result_type>::type& value) = 0;
410 virtual void set_value(
typename transwarp::decay<result_type>::type&& value) = 0;
411 virtual const std::shared_future<result_type>& get_future()
const noexcept = 0;
412 virtual typename transwarp::result_info<result_type>::type
get()
const = 0;
416 template<
typename ResultType>
419 using result_type = ResultType&;
421 virtual ~
task() =
default;
423 virtual void set_value(
typename transwarp::decay<result_type>::type& value) = 0;
424 virtual const std::shared_future<result_type>& get_future()
const noexcept = 0;
425 virtual typename transwarp::result_info<result_type>::type
get()
const = 0;
432 using result_type = void;
434 virtual ~
task() =
default;
436 virtual void set_value() = 0;
437 virtual const std::shared_future<result_type>& get_future()
const noexcept = 0;
438 virtual result_type
get()
const = 0;
453 return transwarp_node_;
459 if (transwarp_node_->is_canceled()) {
468 std::shared_ptr<transwarp::node> transwarp_node_;
483 static void set_level(
transwarp::node& node, std::size_t level) noexcept {
491 static void set_name(
transwarp::node& node, std::shared_ptr<std::string> name) noexcept {
497 node.executor_ = std::move(executor);
499 node.executor_.reset();
503 static void add_parent(
transwarp::node& node, std::shared_ptr<transwarp::node> parent) {
504 node.parents_.push_back(std::move(parent));
507 static void set_priority(
transwarp::node& node, std::size_t priority) noexcept {
508 node.priority_ = priority;
511 static void set_custom_data(
transwarp::node& node, std::shared_ptr<void> custom_data) {
513 node.custom_data_ = std::move(custom_data);
515 node.custom_data_.reset();
519 static void set_canceled(
transwarp::node& node,
bool enabled) noexcept {
520 node.canceled_ = enabled;
533 if (n_threads == 0) {
536 const auto n_target = threads_.size() + n_threads;
537 while (threads_.size() < n_target) {
540 thread = std::thread(&thread_pool::worker,
this);
546 threads_.push_back(std::move(thread));
565 void push(
const std::function<
void()>&
functor) {
567 std::lock_guard<std::mutex> lock(mutex_);
570 cond_var_.notify_one();
579 std::unique_lock<std::mutex> lock(mutex_);
580 cond_var_.wait(lock, [
this]{
581 return done_ || !functors_.empty();
583 if (done_ && functors_.empty()) {
586 functor = functors_.front();
595 std::lock_guard<std::mutex> lock(mutex_);
598 cond_var_.notify_all();
599 for (
auto& thread : threads_) {
606 std::vector<std::thread> threads_;
607 std::queue<std::function<void()>> functors_;
608 std::condition_variable cond_var_;
613 template<
int offset,
typename... ParentResults>
615 static void work(
const std::tuple<std::shared_ptr<
transwarp::task<ParentResults>>...>& source, std::tuple<std::shared_future<ParentResults>...>& target) {
616 std::get<offset>(target) = std::get<offset>(source)->get_future();
621 template<
typename... ParentResults>
627 template<
typename... ParentResults>
629 std::tuple<std::shared_future<ParentResults>...>
result;
635 template<
typename ParentResultType>
637 std::vector<std::shared_future<ParentResultType>>
result;
638 result.reserve(input.size());
639 for (
const auto&
task : input) {
640 result.emplace_back(
task->get_future());
647 template<
typename Result,
typename Task,
typename... Args>
648 Result
run_task(std::size_t node_id,
const Task&
task, Args&&... args) {
649 auto t = task.lock();
653 if (t->node_->is_canceled()) {
657 return t->functor_(std::forward<Args>(args)...);
661 inline void wait_for_all() {}
664 template<
typename ParentResult,
typename... ParentResults>
666 parent->get_future().wait();
672 template<
typename ParentResultType>
674 for (
const auto& parent :
parents) {
675 parent->get_future().wait();
680 template<
typename Parent>
681 Parent wait_for_any_impl() {
685 template<
typename Parent,
typename ParentResult,
typename... ParentResults>
687 const auto status = parent->get_future().wait_for(std::chrono::microseconds(1));
688 if (status == std::future_status::ready) {
691 return transwarp::detail::wait_for_any_impl<Parent>(parents...);
695 template<
typename Parent,
typename... ParentResults>
698 auto parent = transwarp::detail::wait_for_any_impl<Parent>(
parents...);
707 template<
typename ParentResultType>
710 for (
const auto& parent :
parents) {
711 const auto status = parent->get_future().wait_for(std::chrono::microseconds(1));
712 if (status == std::future_status::ready) {
720 template<
typename OneResult>
724 template<
typename OneResult,
typename ParentResult,
typename... ParentResults>
727 parent->cancel(
true);
734 template<
typename OneResult,
typename ParentResultType>
736 for (
const auto& parent :
parents) {
738 parent->cancel(
true);
744 template<
typename TaskType,
bool done,
int total,
int... n>
746 template<
typename Result,
typename Task,
typename... ParentResults>
749 work<Result>(node_id, task,
parents);
753 template<
typename TaskType>
756 template<
int total,
int... n>
758 template<
typename Result,
typename Task,
typename... ParentResults>
760 return transwarp::detail::run_task<Result>(node_id, task);
766 template<
typename Result,
typename Task,
typename ParentResultType>
768 return transwarp::detail::run_task<Result>(node_id, task);
772 template<
int total,
int... n>
774 template<
typename Result,
typename Task,
typename... ParentResults>
778 return transwarp::detail::run_task<Result>(node_id, task, std::get<n>(futures)...);
784 template<
typename Result,
typename Task,
typename ParentResultType>
791 template<
int total,
int... n>
793 template<
typename Result,
typename Task,
typename... ParentResults>
795 using parent_t =
typename std::remove_reference<decltype(std::get<0>(
parents))>::type;
796 auto parent = transwarp::detail::wait_for_any<parent_t>(std::get<n>(
parents)...);
798 return transwarp::detail::run_task<Result>(node_id, task, parent->get_future());
804 template<
typename Result,
typename Task,
typename ParentResultType>
808 return transwarp::detail::run_task<Result>(node_id, task, parent->get_future());
812 template<
int total,
int... n>
814 template<
typename Result,
typename Task,
typename... ParentResults>
817 return transwarp::detail::run_task<Result>(node_id, task, std::get<n>(
parents)->get_future().get()...);
823 template<
typename Result,
typename Task,
typename ParentResultType>
826 std::vector<ParentResultType> results;
827 results.reserve(
parents.size());
828 for (
const auto& parent :
parents) {
829 results.emplace_back(parent->get_future().get());
831 return transwarp::detail::run_task<Result>(node_id, task, std::move(results));
835 template<
int total,
int... n>
837 template<
typename Result,
typename Task,
typename... ParentResults>
839 using parent_t =
typename std::remove_reference<decltype(std::get<0>(
parents))>::type;
840 auto parent = transwarp::detail::wait_for_any<parent_t>(std::get<n>(
parents)...);
842 return transwarp::detail::run_task<Result>(node_id, task, parent->get_future().get());
848 template<
typename Result,
typename Task,
typename ParentResultType>
852 return transwarp::detail::run_task<Result>(node_id, task, parent->get_future().get());
856 template<
int total,
int... n>
858 template<
typename Result,
typename Task,
typename... ParentResults>
861 get_all(std::get<n>(
parents)...);
862 return transwarp::detail::run_task<Result>(node_id, task);
864 template<
typename T,
typename... Args>
865 static void get_all(
const T& arg,
const Args& ...args) {
866 arg->get_future().get();
869 static void get_all() {}
874 template<
typename Result,
typename Task,
typename ParentResultType>
877 for (
const auto& parent :
parents) {
878 parent->get_future().get();
880 return transwarp::detail::run_task<Result>(node_id, task);
884 template<
int total,
int... n>
886 template<
typename Result,
typename Task,
typename... ParentResults>
888 using parent_t =
typename std::remove_reference<decltype(std::get<0>(
parents))>::type;
889 auto parent = transwarp::detail::wait_for_any<parent_t>(std::get<n>(
parents)...);
891 parent->get_future().get();
892 return transwarp::detail::run_task<Result>(node_id, task);
898 template<
typename Result,
typename Task,
typename ParentResultType>
902 parent->get_future().get();
903 return transwarp::detail::run_task<Result>(node_id, task);
910 template<
typename TaskType,
typename Result,
typename Task,
typename... ParentResults>
912 constexpr std::size_t n = std::tuple_size<std::tuple<std::shared_future<ParentResults>...>>::value;
914 work<Result>(node_id, task,
parents);
920 template<
typename TaskType,
typename Result,
typename Task,
typename ParentResultType>
923 work<Result>(node_id, task,
parents);
930 template<std::size_t end, std::size_t idx, std::size_t... i>
933 template<std::size_t end, std::size_t... i>
938 template<std::
size_t b, std::
size_t e>
943 template<
typename Functor,
typename... ParentResults>
946 template<std::size_t i, std::size_t... j,
typename Functor,
typename... ParentResults>
948 auto ptr = std::get<i>(t);
957 template<
typename Functor,
typename... ParentResults>
959 constexpr std::size_t n = std::tuple_size<std::tuple<std::shared_ptr<transwarp::task<ParentResults>>...>>::value;
960 using index_t =
typename transwarp::detail::index_range<0, n>::type;
961 transwarp::detail::call_with_each_index(index_t(), f, t);
965 template<
typename Functor,
typename ParentResultType>
967 for (
const auto& ptr : v) {
982 transwarp::detail::node_manip::add_parent(*node_, task.get_node());
983 if (node_->get_level() <= task.get_node()->get_level()) {
985 transwarp::detail::node_manip::set_level(*node_, task.get_node()->get_level() + 1);
989 std::shared_ptr<transwarp::node>& node_;
998 task.set_node_id(id_++);
1006 explicit graph_visitor(std::vector<transwarp::edge>& graph) noexcept
1010 const auto&
node = task.get_node();
1012 graph_.emplace_back(parent,
node);
1016 std::vector<transwarp::edge>& graph_;
1022 : reset_(reset), executor_(executor) {}
1025 task.schedule_impl(reset_, executor_);
1035 template<
typename Task>
1036 void operator()(Task&
task)
const {
1044 : enabled_(enabled) {}
1047 task.cancel(enabled_);
1056 : executor_(std::move(executor)) {}
1059 task.set_executor(executor_);
1062 std::shared_ptr<transwarp::executor> executor_;
1069 task.remove_executor();
1076 : priority_(priority) {}
1079 task.set_priority(priority_);
1082 std::size_t priority_;
1089 task.reset_priority();
1096 : custom_data_(std::move(custom_data)) {}
1099 task.set_custom_data(custom_data_);
1102 std::shared_ptr<void> custom_data_;
1109 task.remove_custom_data();
1119 tasks_.push_back(&task);
1122 std::vector<transwarp::itask*>& tasks_;
1128 : visitor_(visitor) {}
1131 task.visit_depth(visitor_);
1134 const std::function<void(transwarp::itask&)>& visitor_;
1146 template<
typename TaskType,
typename Functor,
typename... ParentResults>
1148 static_assert(std::is_same<TaskType, transwarp::root_type>::value ||
1149 std::is_same<TaskType, transwarp::accept_type>::value ||
1150 std::is_same<TaskType, transwarp::accept_any_type>::value ||
1151 std::is_same<TaskType, transwarp::consume_type>::value ||
1152 std::is_same<TaskType, transwarp::consume_any_type>::value ||
1153 std::is_same<TaskType, transwarp::wait_type>::value ||
1154 std::is_same<TaskType, transwarp::wait_any_type>::value,
1155 "Invalid task type, must be one of: root, accept, accept_any, consume, consume_any, wait, wait_any");
1158 template<
typename Functor,
typename... ParentResults>
1160 static_assert(
sizeof...(ParentResults) == 0,
"A root task cannot have parent tasks");
1161 using type = decltype(std::declval<Functor>()());
1164 template<
typename Functor,
typename... ParentResults>
1166 static_assert(
sizeof...(ParentResults) > 0,
"An accept task must have at least one parent");
1167 using type = decltype(std::declval<Functor>()(std::declval<std::shared_future<ParentResults>>()...));
1170 template<
typename Functor,
typename ParentResultType>
1171 struct result<transwarp::
accept_type, Functor, std::vector<std::shared_ptr<transwarp::task<ParentResultType>>>> {
1172 using type = decltype(std::declval<Functor>()(std::declval<std::vector<std::shared_future<ParentResultType>>>()));
1175 template<
typename Functor,
typename... ParentResults>
1177 static_assert(
sizeof...(ParentResults) > 0,
"An accept_any task must have at least one parent");
1178 using arg_t =
typename std::tuple_element<0, std::tuple<ParentResults...>>
::type;
1179 using type = decltype(std::declval<Functor>()(std::declval<std::shared_future<arg_t>>()));
1182 template<
typename Functor,
typename ParentResultType>
1184 using type = decltype(std::declval<Functor>()(std::declval<std::shared_future<ParentResultType>>()));
1187 template<
typename Functor,
typename... ParentResults>
1189 static_assert(
sizeof...(ParentResults) > 0,
"A consume task must have at least one parent");
1190 using type = decltype(std::declval<Functor>()(std::declval<ParentResults>()...));
1193 template<
typename Functor,
typename ParentResultType>
1194 struct result<transwarp::
consume_type, Functor, std::vector<std::shared_ptr<transwarp::task<ParentResultType>>>> {
1195 using type = decltype(std::declval<Functor>()(std::declval<std::vector<ParentResultType>>()));
1198 template<
typename Functor,
typename... ParentResults>
1200 static_assert(
sizeof...(ParentResults) > 0,
"A consume_any task must have at least one parent");
1201 using arg_t =
typename std::tuple_element<0, std::tuple<ParentResults...>>
::type;
1202 using type = decltype(std::declval<Functor>()(std::declval<arg_t>()));
1205 template<
typename Functor,
typename ParentResultType>
1207 using type = decltype(std::declval<Functor>()(std::declval<ParentResultType>()));
1210 template<
typename Functor,
typename... ParentResults>
1212 static_assert(
sizeof...(ParentResults) > 0,
"A wait task must have at least one parent");
1213 using type = decltype(std::declval<Functor>()());
1216 template<
typename Functor,
typename ParentResultType>
1217 struct result<transwarp::
wait_type, Functor, std::vector<std::shared_ptr<transwarp::task<ParentResultType>>>> {
1218 using type = decltype(std::declval<Functor>()());
1221 template<
typename Functor,
typename... ParentResults>
1223 static_assert(
sizeof...(ParentResults) > 0,
"A wait_any task must have at least one parent");
1224 using type = decltype(std::declval<Functor>()());
1227 template<
typename Functor,
typename ParentResultType>
1228 struct result<transwarp::
wait_any_type, Functor, std::vector<std::shared_ptr<transwarp::task<ParentResultType>>>> {
1229 using type = decltype(std::declval<Functor>()());
1232 template<
bool is_transwarp_functor>
1237 template<
typename Functor>
1238 void operator()(Functor&
functor, std::shared_ptr<transwarp::node>
node)
const noexcept {
1239 functor.transwarp_node_ = std::move(node);
1245 template<
typename Functor>
1246 void operator()(Functor&, std::shared_ptr<transwarp::node>)
const noexcept {}
1250 template<
typename Functor>
1256 template<
typename ResultType,
typename Value>
1258 std::promise<ResultType> promise;
1259 promise.set_value(std::forward<Value>(value));
1260 return promise.get_future();
1265 std::promise<void> promise;
1266 promise.set_value();
1267 return promise.get_future();
1271 template<
typename ResultType>
1276 std::promise<ResultType> promise;
1277 promise.set_exception(exception);
1278 return promise.get_future();
1283 template<
typename... ParentResults>
1285 using type = std::tuple<std::shared_ptr<transwarp::task<ParentResults>>...>;
1289 template<
typename ParentResultType>
1290 struct parents<std::vector<std::shared_ptr<transwarp::task<ParentResultType>>>> {
1291 using type = std::vector<std::shared_ptr<transwarp::task<ParentResultType>>>;
1296 template<
typename TaskType,
typename ResultType,
typename Task,
typename Parents>
1299 const std::size_t node_id;
1300 const typename transwarp::decay<Task>::type
task;
1301 const typename transwarp::decay<Parents>::type
parents;
1303 ResultType operator()() {
1305 return transwarp::detail::call<TaskType, ResultType>(node_id,
task,
parents);
1307 if (
const auto t =
task.lock()) {
1333 return "transwarp::sequential";
1337 void execute(
const std::function<
void()>&
functor,
const std::shared_ptr<transwarp::node>&)
override {
1347 explicit parallel(std::size_t n_threads)
1359 return "transwarp::parallel";
1363 void execute(
const std::function<
void()>&
functor,
const std::shared_ptr<transwarp::node>&)
override {
1377 template<
typename ResultType,
typename TaskType,
typename Functor,
typename... ParentResults>
1379 public std::enable_shared_from_this<task_impl_base<ResultType, TaskType, Functor, ParentResults...>> {
1385 using result_type = ResultType;
1394 executor_ = std::move(executor);
1395 transwarp::detail::node_manip::set_executor(*node_, std::make_shared<std::string>(executor_->get_name()));
1403 visit_depth_all(visitor);
1410 transwarp::detail::node_manip::set_executor(*node_,
nullptr);
1417 visit_depth_all(visitor);
1424 transwarp::detail::node_manip::set_priority(*node_, priority);
1432 visit_depth_all(visitor);
1438 transwarp::detail::node_manip::set_priority(*node_, 0);
1445 visit_depth_all(visitor);
1455 transwarp::detail::node_manip::set_custom_data(*node_, std::move(custom_data));
1463 visit_depth_all(visitor);
1469 transwarp::detail::node_manip::set_custom_data(*node_,
nullptr);
1476 visit_depth_all(visitor);
1480 const std::shared_future<result_type>&
get_future() const noexcept
override {
1485 const std::shared_ptr<transwarp::node>&
get_node() const noexcept
override {
1492 check_listener(listener);
1493 for (
auto& l : listeners_) {
1494 l.push_back(listener);
1501 check_listener(listener);
1502 listeners_[get_event_index(event)].push_back(std::move(listener));
1508 check_listener(listener);
1509 for (
auto& l : listeners_) {
1510 l.erase(std::remove(l.begin(), l.end(), listener), l.end());
1517 check_listener(listener);
1518 auto& l = listeners_[get_event_index(event)];
1519 l.erase(std::remove(l.begin(), l.end(), listener), l.end());
1525 listeners_[get_event_index(event)].clear();
1531 for (
auto& l : listeners_) {
1541 this->schedule_impl(
true);
1550 this->schedule_impl(reset);
1558 this->schedule_impl(
true, &executor);
1567 this->schedule_impl(reset, &executor);
1609 schedule_all_impl(
true, type);
1617 schedule_all_impl(
true, type, &executor);
1626 schedule_all_impl(reset_all, type);
1635 schedule_all_impl(reset_all, type, &executor);
1642 future_ = transwarp::detail::make_future_with_exception<result_type>(exception);
1643 schedule_mode_ =
false;
1649 return future_.valid();
1663 return future_.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
1674 future_ = std::shared_future<result_type>();
1675 transwarp::detail::node_manip::set_canceled(*node_,
false);
1676 schedule_mode_ =
true;
1683 visit_depth_all(visitor);
1689 void cancel(
bool enabled) noexcept
override {
1690 transwarp::detail::node_manip::set_canceled(*node_, enabled);
1698 visit_depth_all(visitor);
1705 std::vector<transwarp::edge> graph;
1713 template<
typename F>
1716 : node_(std::make_shared<transwarp::
node>()),
1717 functor_(std::forward<F>(
functor)),
1718 parents_(std::make_tuple(std::move(
parents)...)),
1719 listeners_(static_cast<std::size_t>(transwarp::
event_type::count))
1721 init(has_name, std::move(name));
1724 template<
typename F,
typename P>
1727 : node_(std::make_shared<transwarp::
node>()),
1728 functor_(std::forward<F>(
functor)),
1729 parents_(std::move(parents)),
1730 listeners_(static_cast<std::size_t>(transwarp::
event_type::count))
1732 if (parents_.empty()) {
1735 init(has_name, std::move(name));
1738 void init(
bool has_name, std::string name) {
1739 transwarp::detail::node_manip::set_type(*node_, task_type::value);
1740 transwarp::detail::node_manip::set_name(*node_, (has_name ? std::make_shared<std::string>(std::move(name)) :
nullptr));
1744 visit_depth(visitor);
1750 if (future_.valid() && future_.wait_for(std::chrono::seconds(0)) != std::future_status::ready) {
1757 if (!future_.valid()) {
1762 bool schedule_mode_ =
true;
1763 std::shared_future<result_type> future_;
1767 template<
typename Y,
typename R,
typename T,
typename P>
1770 template<
typename R,
typename T,
typename... A>
1774 void set_node_id(std::size_t
id) noexcept
override {
1775 transwarp::detail::node_manip::set_id(*node_,
id);
1783 if (schedule_mode_ && (reset || !future_.valid())) {
1785 transwarp::detail::node_manip::set_canceled(*node_,
false);
1787 std::weak_ptr<task_impl_base>
self = this->shared_from_this();
1788 auto pack_task = std::make_shared<std::packaged_task<result_type()>>(
1791 future_ = pack_task->get_future();
1792 auto callable = [pack_task,
self] {
1793 if (
const auto t =
self.lock()) {
1797 if (
const auto t =
self.lock()) {
1802 executor_->execute(callable, node_);
1803 }
else if (executor) {
1804 executor->execute(callable, node_);
1819 visit_breadth_all(visitor);
1822 visit_depth_all(visitor);
1830 template<
typename Visitor>
1831 void visit_breadth_all(Visitor& visitor) {
1832 if (breadth_tasks_.empty()) {
1833 breadth_tasks_.reserve(node_->get_id() + 1);
1837 const auto l_level = l->get_node()->get_level();
1838 const auto l_id = l->get_node()->get_id();
1839 const auto r_level = r->get_node()->get_level();
1840 const auto r_id = r->get_node()->get_id();
1841 return std::tie(l_level, l_id) < std::tie(r_level, r_id);
1843 std::sort(breadth_tasks_.begin(), breadth_tasks_.end(), compare);
1845 for (
auto task : breadth_tasks_) {
1851 template<
typename Visitor>
1852 void visit_depth_all(Visitor& visitor) {
1853 if (depth_tasks_.empty()) {
1854 depth_tasks_.reserve(node_->get_id() + 1);
1858 for (
auto task : depth_tasks_) {
1864 void visit_depth(
const std::function<
void(
transwarp::itask&)>& visitor)
override {
1873 void unvisit() noexcept
override {
1882 const auto index =
static_cast<std::size_t
>(event);
1883 if (index >= static_cast<std::size_t>(transwarp::event_type::count)) {
1891 for (
const auto& listener : listeners_[static_cast<std::size_t>(event)]) {
1892 listener->handle_event(event,
get_node());
1897 void check_listener(
const std::shared_ptr<transwarp::listener>& listener)
const {
1903 std::shared_ptr<transwarp::node> node_;
1906 bool visited_ =
false;
1907 std::shared_ptr<transwarp::executor> executor_;
1908 std::vector<std::vector<std::shared_ptr<transwarp::listener>>> listeners_;
1909 std::vector<transwarp::itask*> depth_tasks_;
1910 std::vector<transwarp::itask*> breadth_tasks_;
1915 template<
typename ResultType,
typename TaskType,
typename Functor,
typename... ParentResults>
1922 using result_type = ResultType;
1926 void set_value(
const typename transwarp::decay<result_type>::type& value)
override {
1927 set_value_impl(value);
1932 void set_value(
typename transwarp::decay<result_type>::type&& value)
override {
1933 set_value_impl(value);
1939 typename transwarp::result_info<result_type>::type
get()
const override {
1941 return this->future_.get();
1946 template<
typename F>
1953 template<
typename F>
1956 : transwarp::detail::task_impl_base<
result_type,
task_type, Functor, ParentResults...>(false,
"", std::forward<F>(
functor), std::move(parents)...)
1959 template<
typename F,
typename P>
1962 task_impl_proxy(std::string name, F&& functor, std::vector<std::shared_ptr<
transwarp::task<P>>> parents)
1963 : transwarp::detail::task_impl_base<
result_type,
task_type, Functor, ParentResults...>(true, std::move(name), std::forward<F>(functor), std::move(parents))
1966 template<
typename F,
typename P>
1968 task_impl_proxy(F&& functor, std::vector<std::shared_ptr<
transwarp::task<P>>> parents)
1969 : transwarp::detail::task_impl_base<
result_type,
task_type, Functor, ParentResults...>(false,
"", std::forward<F>(functor), std::move(parents))
1974 template<
typename T>
1975 void set_value_impl(T&& value) {
1977 this->future_ = transwarp::detail::make_future_with_value<result_type>(std::forward<T>(value));
1978 this->schedule_mode_ =
false;
1984 template<
typename ResultType,
typename TaskType,
typename Functor,
typename... ParentResults>
1991 using result_type = ResultType&;
1995 void set_value(
typename transwarp::decay<result_type>::type& value)
override {
1996 set_value_impl(value);
2002 typename transwarp::result_info<result_type>::type
get()
const override {
2003 this->ensure_task_was_scheduled();
2004 return this->future_.get();
2009 template<
typename F>
2016 template<
typename F>
2019 : transwarp::detail::task_impl_base<result_type,
task_type, Functor, ParentResults...>(false,
"", std::forward<F>(
functor), std::move(parents)...)
2022 template<
typename F,
typename P>
2025 task_impl_proxy(std::string name, F&& functor, std::vector<std::shared_ptr<
transwarp::task<P>>> parents)
2026 : transwarp::detail::task_impl_base<result_type,
task_type, Functor, ParentResults...>(true, std::move(name), std::forward<F>(functor), std::move(parents))
2029 template<
typename F,
typename P>
2031 task_impl_proxy(F&& functor, std::vector<std::shared_ptr<
transwarp::task<P>>> parents)
2032 : transwarp::detail::task_impl_base<result_type,
task_type, Functor, ParentResults...>(false,
"", std::forward<F>(functor), std::move(parents))
2037 template<
typename T>
2038 void set_value_impl(T&& value) {
2039 this->ensure_task_not_running();
2040 this->future_ = transwarp::detail::make_future_with_value<result_type>(std::forward<T>(value));
2041 this->schedule_mode_ =
false;
2047 template<
typename TaskType,
typename Functor,
typename... ParentResults>
2054 using result_type = void;
2061 this->schedule_mode_ =
false;
2067 void get()
const override {
2069 this->future_.get();
2074 template<
typename F>
2081 template<
typename F>
2084 : transwarp::detail::task_impl_base<
result_type,
task_type, Functor, ParentResults...>(false,
"", std::forward<F>(
functor), std::move(parents)...)
2087 template<
typename F,
typename P>
2090 task_impl_proxy(std::string name, F&& functor, std::vector<std::shared_ptr<
transwarp::task<P>>> parents)
2091 : transwarp::detail::task_impl_base<
result_type,
task_type, Functor, ParentResults...>(true, std::move(name), std::forward<F>(functor), std::move(parents))
2094 template<
typename F,
typename P>
2096 task_impl_proxy(F&& functor, std::vector<std::shared_ptr<
transwarp::task<P>>> parents)
2097 : transwarp::detail::task_impl_base<
result_type,
task_type, Functor, ParentResults...>(false,
"", std::forward<F>(functor), std::move(parents))
2108 template<
typename TaskType,
typename Functor,
typename... ParentResults>
2119 template<typename F, typename = typename std::enable_if<std::is_same<Functor, typename std::decay<F>::type>::value>::type>
2123 : transwarp::detail::task_impl_proxy<
result_type,
task_type, Functor, ParentResults...>(std::move(name), std::forward<F>(
functor), std::move(parents)...)
2128 template<typename F, typename = typename std::enable_if<std::is_same<Functor, typename std::decay<F>::type>::value>::type>
2131 : transwarp::detail::task_impl_proxy<
result_type,
task_type, Functor, ParentResults...>(std::forward<F>(
functor), std::move(parents)...)
2136 template<typename F, typename P, typename = typename std::enable_if<std::is_same<Functor, typename std::decay<F>::type>::value>::type>
2139 : transwarp::detail::task_impl_proxy<
result_type,
task_type, Functor, ParentResults...>(std::move(name), std::forward<F>(
functor), std::move(parents))
2144 template<typename F, typename P, typename = typename std::enable_if<std::is_same<Functor, typename std::decay<F>::type>::value>::type>
2147 : transwarp::detail::task_impl_proxy<
result_type,
task_type, Functor, ParentResults...>(std::forward<F>(
functor), std::move(parents))
2151 template<
typename TaskType_,
typename Functor_>
2154 return std::make_shared<transwarp::task_impl<TaskType_, typename std::decay<Functor_>::type,
result_type>>(std::move(name), std::forward<Functor_>(functor), std::dynamic_pointer_cast<
transwarp::task<result_type>>(const_cast<task_impl*>(
this)->shared_from_this()));
2158 template<
typename TaskType_,
typename Functor_>
2161 return std::make_shared<transwarp::task_impl<TaskType_, typename std::decay<Functor_>::type,
result_type>>(std::forward<Functor_>(functor), std::dynamic_pointer_cast<
transwarp::task<result_type>>(const_cast<task_impl*>(
this)->shared_from_this()));
2174 template<
typename ResultType>
2176 public std::enable_shared_from_this<value_task<ResultType>> {
2186 template<typename T, typename = typename std::enable_if<std::is_same<result_type, typename transwarp::decay<T>::type>::value>::type>
2190 :
value_task(true, std::move(name), std::forward<T>(value))
2195 template<typename T, typename = typename std::enable_if<std::is_same<result_type, typename transwarp::decay<T>::type>::value>::type>
2198 :
value_task(false,
"", std::forward<T>(value))
2210 template<
typename TaskType_,
typename Functor_>
2213 return std::make_shared<transwarp::task_impl<TaskType_, typename std::decay<Functor_>::type,
result_type>>(std::move(name), std::forward<Functor_>(functor), std::dynamic_pointer_cast<
transwarp::task<result_type>>(const_cast<value_task*>(
this)->shared_from_this()));
2217 template<
typename TaskType_,
typename Functor_>
2220 return std::make_shared<transwarp::task_impl<TaskType_, typename std::decay<Functor_>::type,
result_type>>(std::forward<Functor_>(functor), std::dynamic_pointer_cast<
transwarp::task<result_type>>(const_cast<value_task*>(
this)->shared_from_this()));
2238 transwarp::detail::node_manip::set_priority(*node_, priority);
2249 transwarp::detail::node_manip::set_priority(*node_, 0);
2263 transwarp::detail::node_manip::set_custom_data(*node_, std::move(custom_data));
2274 transwarp::detail::node_manip::set_custom_data(*node_,
nullptr);
2283 const std::shared_future<result_type>&
get_future() const noexcept
override {
2288 const std::shared_ptr<transwarp::node>&
get_node() const noexcept
override {
2347 void set_value(
const typename transwarp::decay<result_type>::type& value)
override {
2348 future_ = transwarp::detail::make_future_with_value<result_type>(value);
2352 void set_value(
typename transwarp::decay<result_type>::type&& value)
override {
2353 future_ = transwarp::detail::make_future_with_value<result_type>(value);
2358 future_ = transwarp::detail::make_future_with_exception<result_type>(exception);
2380 typename transwarp::result_info<result_type>::type
get()
const override {
2381 return future_.get();
2403 template<
typename T>
2405 value_task(
bool has_name, std::string name, T&& value)
2406 : node_(std::make_shared<transwarp::
node>()),
2407 future_(transwarp::detail::make_future_with_value<
result_type>(std::forward<T>(value)))
2409 transwarp::detail::node_manip::set_type(*node_, task_type::value);
2410 transwarp::detail::node_manip::set_name(*node_, (has_name ? std::make_shared<std::string>(std::move(name)) :
nullptr));
2414 void set_node_id(std::size_t
id) noexcept
override {
2415 transwarp::detail::node_manip::set_id(*node_,
id);
2422 void visit_depth(
const std::function<
void(
transwarp::itask&)>& visitor)
override {
2430 void unvisit() noexcept
override {
2434 std::shared_ptr<transwarp::node> node_;
2435 std::shared_future<result_type> future_;
2436 bool visited_ =
false;
2441 template<
typename TaskType,
typename Functor,
typename... Parents>
2442 auto make_task(TaskType, std::string name, Functor&&
functor, std::shared_ptr<Parents>... parents)
2443 -> decltype(std::make_shared<
transwarp::task_impl<TaskType,
typename std::decay<Functor>::type,
typename Parents::result_type...>>(std::move(name), std::forward<Functor>(
functor), std::move(parents)...)) {
2444 return std::make_shared<transwarp::task_impl<TaskType, typename std::decay<Functor>::type,
typename Parents::result_type...>>(std::move(name), std::forward<Functor>(
functor), std::move(parents)...);
2448 template<
typename TaskType,
typename Functor,
typename... Parents>
2450 -> decltype(std::make_shared<
transwarp::task_impl<TaskType,
typename std::decay<Functor>::type,
typename Parents::result_type...>>(std::forward<Functor>(
functor), std::move(parents)...)) {
2451 return std::make_shared<transwarp::task_impl<TaskType, typename std::decay<Functor>::type,
typename Parents::result_type...>>(std::forward<Functor>(
functor), std::move(parents)...);
2456 template<
typename TaskType,
typename Functor,
typename ParentType>
2458 -> decltype(std::make_shared<
transwarp::task_impl<TaskType,
typename std::decay<Functor>::type, decltype(parents)>>(std::move(name), std::forward<Functor>(
functor), std::move(parents))) {
2459 return std::make_shared<transwarp::task_impl<TaskType, typename std::decay<Functor>::type, decltype(parents)>>(std::move(name), std::forward<Functor>(
functor), std::move(parents));
2463 template<
typename TaskType,
typename Functor,
typename ParentType>
2465 -> decltype(std::make_shared<
transwarp::task_impl<TaskType,
typename std::decay<Functor>::type, decltype(parents)>>(std::forward<Functor>(
functor), std::move(parents))) {
2466 return std::make_shared<transwarp::task_impl<TaskType, typename std::decay<Functor>::type, decltype(parents)>>(std::forward<Functor>(
functor), std::move(parents));
2471 template<
typename Value>
2473 -> decltype(std::make_shared<
transwarp::value_task<
typename transwarp::decay<Value>::type>>(std::move(name), std::forward<Value>(value))) {
2474 return std::make_shared<transwarp::value_task<typename transwarp::decay<Value>::type>>(std::move(name), std::forward<Value>(value));
2478 template<
typename Value>
2480 -> decltype(std::make_shared<
transwarp::value_task<
typename transwarp::decay<Value>::type>>(std::forward<Value>(value))) {
2481 return std::make_shared<transwarp::value_task<typename transwarp::decay<Value>::type>>(std::forward<Value>(value));
void set_custom_data_all(std::shared_ptr< void > custom_data) override
Assigns custom data to all tasks. transwarp will not directly use this. This is only useful if someth...
Definition: transwarp.h:1460
constexpr transwarp::wait_any_type wait_any
The wait_any task tag.
Definition: transwarp.h:127
void remove_custom_data_all() override
Removes custom data from all tasks.
Definition: transwarp.h:2278
The executor interface used to perform custom task execution.
Definition: transwarp.h:282
Exception thrown when a task was destroyed prematurely.
Definition: transwarp.h:60
A simple thread pool used to execute tasks in parallel.
Definition: transwarp.h:527
void cancel_all(bool) noexceptoverride
No-op because a value task never runs and doesn't have parents.
Definition: transwarp.h:2394
void operator()(const transwarp::itask &task) const
Definition: transwarp.h:981
Node manipulation.
Definition: transwarp.h:477
TaskType task_type
The task type.
Definition: transwarp.h:1988
void remove_listeners(transwarp::event_type) override
No-op because a value task doesn't raise events.
Definition: transwarp.h:2305
Generates a graph.
Definition: transwarp.h:1005
The consume type. Used for tag dispatch.
Definition: transwarp.h:114
void schedule_all(transwarp::executor &) override
No-op because a value task never runs and doesn't have parents.
Definition: transwarp.h:2326
Removes the executor from the given task.
Definition: transwarp.h:1066
Definition: transwarp.h:928
void reset_priority_all() override
Resets the priority of all tasks to 0.
Definition: transwarp.h:1442
Definition: transwarp.h:139
just after a task was canceled (handle_event called on thread that task is run on) ...
TaskType task_type
The task type.
Definition: transwarp.h:2051
void set_exception(std::exception_ptr exception) override
Assigns an exception to this task.
Definition: transwarp.h:2357
void schedule_all(bool reset_all) override
Schedules all tasks in the graph for execution on the caller thread. The task-specific executors get ...
Definition: transwarp.h:1590
void ensure_task_was_scheduled() const
Checks if the task was scheduled and throws transwarp::control_error if it's not. ...
Definition: transwarp.h:1756
Sets parents and level of the node.
Definition: transwarp.h:977
value_task(std::string name, T &&value)
A value task is defined by name and value. name is optional, see overload Note: A value task must be ...
Definition: transwarp.h:2189
void set_executor(std::shared_ptr< transwarp::executor >) override
No-op because a value task never runs.
Definition: transwarp.h:2224
void set_executor_all(std::shared_ptr< transwarp::executor > executor) override
Assigns an executor to all tasks which takes precedence over the executor provided in schedule() or s...
Definition: transwarp.h:1400
bool was_scheduled() const noexceptoverride
Returns whether the task was scheduled and not reset afterwards. This means that the underlying futur...
Definition: transwarp.h:1648
void cancel(bool) noexceptoverride
No-op because a value task never runs.
Definition: transwarp.h:2391
just before a task is scheduled (handle_event called on thread of caller to schedule()) ...
void schedule_all() override
No-op because a value task never runs and doesn't have parents.
Definition: transwarp.h:2323
void schedule_all(transwarp::executor &executor, bool reset_all) override
Schedules all tasks in the graph for execution using the provided executor. The task-specific executo...
Definition: transwarp.h:1599
std::string get_name() const override
Returns the name of the executor.
Definition: transwarp.h:1358
Assigns a priority to the given task.
Definition: transwarp.h:1074
void set_value(const typename transwarp::decay< result_type >::type &value) override
Assigns a value to this task.
Definition: transwarp.h:2347
void schedule(transwarp::executor &executor) override
Schedules this task for execution using the provided executor. The task-specific executor gets preced...
Definition: transwarp.h:1556
Assigns an executor to the given task.
Definition: transwarp.h:1054
Unvisits the given task.
Definition: transwarp.h:1138
void set_priority(std::size_t priority) override
Sets a task priority (defaults to 0). transwarp will not directly use this. This is only useful if so...
Definition: transwarp.h:2237
void cancel_all(bool enabled) noexceptoverride
If enabled then all pending tasks in the graph are canceled which will throw transwarp::task_canceled...
Definition: transwarp.h:1696
void remove_custom_data() override
Removes custom data from this task.
Definition: transwarp.h:1467
void set_custom_data_all(std::shared_ptr< void > custom_data) override
Assigns custom data to all tasks. transwarp will not directly use this. This is only useful if someth...
Definition: transwarp.h:2268
std::tuple< std::shared_future< ParentResults >...> get_futures(const std::tuple< std::shared_ptr< transwarp::task< ParentResults >>...> &input)
Returns the futures from the given tuple of tasks.
Definition: transwarp.h:628
void set_value(typename transwarp::decay< result_type >::type &&value) override
Assigns a value to this task.
Definition: transwarp.h:2352
void schedule_all(transwarp::schedule_type type, bool reset_all) override
Schedules all tasks in the graph for execution on the caller thread. The task-specific executors get ...
Definition: transwarp.h:1624
Scheduling according to a breadth-first search (default)
void schedule_all() override
Schedules all tasks in the graph for execution on the caller thread. The task-specific executors get ...
Definition: transwarp.h:1573
void set_executor(std::shared_ptr< transwarp::executor > executor) override
Assigns an executor to this task which takes precedence over the executor provided in schedule() or s...
Definition: transwarp.h:1389
void set_custom_data(std::shared_ptr< void > custom_data) override
Assigns custom data to this task. transwarp will not directly use this. This is only useful if someth...
Definition: transwarp.h:2259
The task class (non-void result type)
Definition: transwarp.h:403
value_task(T &&value)
This overload is for omitting the task name Note: A value task must be created using shared_ptr (beca...
Definition: transwarp.h:2197
Definition: transwarp.h:939
void schedule_all(transwarp::executor &executor, transwarp::schedule_type type, bool reset_all) override
Schedules all tasks in the graph for execution using the provided executor. The task-specific executo...
Definition: transwarp.h:1633
decltype(std::declval< Functor >()(std::declval< std::shared_future< arg_t >>())) type
using first type as reference
Definition: transwarp.h:1179
void reset_priority_all() override
Resets the priority of all tasks to 0.
Definition: transwarp.h:2253
void set_value(const typename transwarp::decay< result_type >::type &value) override
Assigns a value to this task. Scheduling will have no effect after a value has been set...
Definition: transwarp.h:1926
void set_priority(std::size_t priority) override
Sets a task priority (defaults to 0). transwarp will not directly use this. This is only useful if so...
Definition: transwarp.h:1422
const std::shared_ptr< std::string > & get_executor() const noexcept
The optional, task-specific executor (may be null)
Definition: transwarp.h:177
void assign_node_if(Functor &functor, std::shared_ptr< transwarp::node > node) noexcept
Assigns the node to the given functor if the functor is a subclass of transwarp::functor.
Definition: transwarp.h:1251
void reset() override
Resets this task.
Definition: transwarp.h:1672
const std::vector< std::shared_ptr< node > > & get_parents() const noexcept
The task's parents (may be empty)
Definition: transwarp.h:182
decltype(std::declval< Functor >()(std::declval< arg_t >())) type
using first type as reference
Definition: transwarp.h:1202
just before a task's functor is invoked (handle_event called on thread that task is run on) ...
Definition: transwarp.h:926
auto then(TaskType_, Functor_ &&functor) const -> decltype(std::make_shared< transwarp::task_impl< TaskType_, typename std::decay< Functor_ >::type, result_type >>(std::forward< Functor_ >(functor), std::dynamic_pointer_cast< transwarp::task< result_type >>(const_cast< value_task * >(this) ->shared_from_this())))
Creates a continuation to this task. Overload for omitting for task name.
Definition: transwarp.h:2218
The task's functor accepts the first parent future that becomes ready.
The consume_any type. Used for tag dispatch.
Definition: transwarp.h:118
ResultType result_type
The result type of this task.
Definition: transwarp.h:1922
void set_custom_data(std::shared_ptr< void > custom_data) override
Assigns custom data to this task. transwarp will not directly use this. This is only useful if someth...
Definition: transwarp.h:1450
bool was_scheduled() const noexceptoverride
Returns true because a value task is scheduled once on construction.
Definition: transwarp.h:2362
void execute(const std::function< void()> &functor, const std::shared_ptr< transwarp::node > &) override
Pushes the functor into the thread pool for asynchronous execution.
Definition: transwarp.h:1363
void wait_for_all(const std::vector< std::shared_ptr< transwarp::task< ParentResultType >>> &parents)
Waits for all parents to finish.
Definition: transwarp.h:673
The accept type. Used for tag dispatch.
Definition: transwarp.h:106
const std::shared_future< result_type > & get_future() const noexceptoverride
Returns the future associated to the underlying execution.
Definition: transwarp.h:1480
constexpr transwarp::accept_type accept
The accept task tag.
Definition: transwarp.h:107
Determines the result type of the Functor dispatching on the task type.
Definition: transwarp.h:1147
TaskType task_type
The task type.
Definition: transwarp.h:1382
void schedule_all(transwarp::executor &, transwarp::schedule_type, bool) override
No-op because a value task never runs and doesn't have parents.
Definition: transwarp.h:2344
void remove_listeners() override
No-op because a value task doesn't raise events.
Definition: transwarp.h:2308
bool has_result() const noexceptoverride
Returns whether this task contains a result.
Definition: transwarp.h:1667
The listener interface to listen to events raised by tasks.
Definition: transwarp.h:309
Exception thrown when a task is canceled.
Definition: transwarp.h:51
TaskType task_type
The task type.
Definition: transwarp.h:2112
void wait() const override
Waits for the task to complete. Should only be called if was_scheduled() is true, throws transwarp::c...
Definition: transwarp.h:1654
Scheduling according to a depth-first search.
void add_listener(transwarp::event_type event, std::shared_ptr< transwarp::listener > listener) override
Adds a new listener for the given event type only.
Definition: transwarp.h:1499
std::size_t get_level() const noexcept
The task level.
Definition: transwarp.h:162
std::shared_future< ResultType > make_future_with_value(Value &&value)
Returns a ready future with the given value as its state.
Definition: transwarp.h:1257
std::string get_name() const override
Returns the name of the executor.
Definition: transwarp.h:1332
void schedule() override
Schedules this task for execution on the caller thread. The task-specific executor gets precedence if...
Definition: transwarp.h:1539
void add_listener(std::shared_ptr< transwarp::listener >) override
No-op because a value task doesn't raise events.
Definition: transwarp.h:2293
void add_listener(std::shared_ptr< transwarp::listener > listener) override
Adds a new listener for all event types.
Definition: transwarp.h:1490
void ensure_task_not_running() const
Checks if the task is currently running and throws transwarp::control_error if it is...
Definition: transwarp.h:1749
just before a task starts running (handle_event called on thread that task is run on) ...
Removes custom data from the given task.
Definition: transwarp.h:1106
void schedule_all(transwarp::executor &, bool) override
No-op because a value task never runs and doesn't have parents.
Definition: transwarp.h:2332
Resets the given task.
Definition: transwarp.h:1033
const std::shared_ptr< std::string > & get_name() const noexcept
The optional task name (may be null)
Definition: transwarp.h:172
A base class for a user-defined functor that needs access to the node associated to the task or a can...
Definition: transwarp.h:444
constexpr transwarp::consume_any_type consume_any
The consume_any task tag.
Definition: transwarp.h:119
bool is_canceled() const noexcept
Returns whether the associated task is canceled.
Definition: transwarp.h:197
A node carrying meta-data of a task.
Definition: transwarp.h:145
Exception thrown when a task is used in unintended ways.
Definition: transwarp.h:78
Resets the priority of the given task.
Definition: transwarp.h:1086
void schedule() override
No-op because a value task never runs.
Definition: transwarp.h:2311
void add_listener(transwarp::event_type, std::shared_ptr< transwarp::listener >) override
No-op because a value task doesn't raise events.
Definition: transwarp.h:2296
void wait() const override
No-op because a value task never runs.
Definition: transwarp.h:2367
void schedule_all(transwarp::executor &executor, transwarp::schedule_type type) override
Schedules all tasks in the graph for execution using the provided executor. The task-specific executo...
Definition: transwarp.h:1615
std::size_t get_priority() const noexcept
The task priority (defaults to 0)
Definition: transwarp.h:187
const std::shared_ptr< transwarp::node > & get_parent() const noexcept
Returns the parent node.
Definition: transwarp.h:250
A task proxy for non-void result type.
Definition: transwarp.h:1916
void transwarp_cancel_point() const
If the associated task is canceled then this will throw transwarp::task_canceled which will stop the ...
Definition: transwarp.h:458
Returns the result type of a std::shared_future<T>
Definition: transwarp.h:396
The base task class that contains the functionality that can be used with all result types (void and ...
Definition: transwarp.h:1378
Definition: transwarp.h:614
task_impl(F &&functor, std::vector< std::shared_ptr< transwarp::task< P >>> parents)
This overload is for omitting the task name Note: A task must be created using shared_ptr (because of...
Definition: transwarp.h:2146
The task's functor consumes all parent results.
auto make_value_task(std::string name, Value &&value) -> decltype(std::make_shared< transwarp::value_task< typename transwarp::decay< Value >::type >>(std::move(name), std::forward< Value >(value)))
A factory function to create a new value task.
Definition: transwarp.h:2472
just after a task has finished running (handle_event called on thread that task is run on) ...
void remove_listener(const std::shared_ptr< transwarp::listener > &) override
No-op because a value task doesn't raise events.
Definition: transwarp.h:2299
void set_priority_all(std::size_t priority) override
Sets a priority to all tasks (defaults to 0). transwarp will not directly use this. This is only useful if something else is using the priority.
Definition: transwarp.h:2243
Base class for exceptions.
Definition: transwarp.h:42
void schedule_all(transwarp::schedule_type) override
No-op because a value task never runs and doesn't have parents.
Definition: transwarp.h:2335
task_impl(std::string name, F &&functor, std::shared_ptr< transwarp::task< ParentResults >>...parents)
A task is defined by name, functor, and parent tasks. name is optional, see overload Note: A task mus...
Definition: transwarp.h:2122
A callable to run a task given its parents.
Definition: transwarp.h:1297
constexpr transwarp::consume_type consume
The consume task tag.
Definition: transwarp.h:115
std::size_t get_id() const noexcept
The task ID.
Definition: transwarp.h:157
void schedule(transwarp::executor &, bool) override
No-op because a value task never runs.
Definition: transwarp.h:2320
A value task that stores a single value and doesn't require scheduling. Value tasks should be created...
Definition: transwarp.h:2175
void reset_priority() override
Resets the task priority to 0.
Definition: transwarp.h:2248
task_impl(std::string name, F &&functor, std::vector< std::shared_ptr< transwarp::task< P >>> parents)
A task is defined by name, functor, and parent tasks. name is optional, see overload Note: A task mus...
Definition: transwarp.h:2138
Result run_task(std::size_t node_id, const Task &task, Args &&...args)
Runs the task with the given arguments, hence, invoking the task's functor.
Definition: transwarp.h:648
void remove_listeners(transwarp::event_type event) override
Removes all listeners for the given event type.
Definition: transwarp.h:1523
void remove_listener(const std::shared_ptr< transwarp::listener > &listener) override
Removes the listener for all event types.
Definition: transwarp.h:1506
Determines the type of the parents.
Definition: transwarp.h:1284
const std::shared_ptr< transwarp::node > & transwarp_node() const noexcept
The node associated to the task.
Definition: transwarp.h:452
Parent wait_for_any(const std::shared_ptr< transwarp::task< ParentResults >> &...parents)
Waits for the first parent to finish.
Definition: transwarp.h:696
void reset_all() override
No-op because a value task never runs and doesn't have parents.
Definition: transwarp.h:2388
void remove_listener(transwarp::event_type event, const std::shared_ptr< transwarp::listener > &listener) override
Removes the listener for the given event type only.
Definition: transwarp.h:1515
Assigns custom data to the given task.
Definition: transwarp.h:1094
The task's functor takes no arguments but waits for all parents to finish.
void set_exception(std::exception_ptr exception) override
Assigns an exception to this task. Scheduling will have no effect after an exception has been set...
Definition: transwarp.h:1640
void cancel_all_but_one(const std::shared_ptr< transwarp::task< OneResult >> &one, const std::vector< std::shared_ptr< transwarp::task< ParentResultType >>> &parents)
Cancels all tasks but one.
Definition: transwarp.h:735
Definition: transwarp.h:754
Removes reference and const from a type.
Definition: transwarp.h:389
void remove_listeners() override
Removes all listeners.
Definition: transwarp.h:1529
const std::shared_ptr< void > & get_custom_data() const noexcept
The custom task data (may be null)
Definition: transwarp.h:192
void call_with_each(const Functor &f, const std::tuple< std::shared_ptr< transwarp::task< ParentResults >>...> &t)
Calls the functor with every element in the tuple.
Definition: transwarp.h:958
void reset_priority() override
Resets the task priority to 0.
Definition: transwarp.h:1436
typename transwarp::detail::result< TaskType, Functor, ParentResults...>::type result_type
The result type of this task.
Definition: transwarp.h:2115
void schedule_all(transwarp::executor &, transwarp::schedule_type) override
No-op because a value task never runs and doesn't have parents.
Definition: transwarp.h:2338
void schedule_all(transwarp::schedule_type, bool) override
No-op because a value task never runs and doesn't have parents.
Definition: transwarp.h:2341
An edge between two nodes.
Definition: transwarp.h:236
const std::shared_ptr< transwarp::node > & get_child() const noexcept
Returns the child node.
Definition: transwarp.h:255
void schedule_all(transwarp::schedule_type type) override
Schedules all tasks in the graph for execution on the caller thread. The task-specific executors get ...
Definition: transwarp.h:1607
std::vector< transwarp::edge > get_graph() const override
Returns the graph of the task structure. This is mainly for visualizing the tasks and their interdepe...
Definition: transwarp.h:1704
void set_value(typename transwarp::decay< result_type >::type &value) override
Assigns a value to this task. Scheduling will have no effect after a value has been set...
Definition: transwarp.h:1995
void schedule(transwarp::executor &) override
No-op because a value task never runs.
Definition: transwarp.h:2314
void reset_all() override
Resets all tasks in the graph.
Definition: transwarp.h:1680
Definition: transwarp.h:745
ResultType result_type
The result type of this task.
Definition: transwarp.h:2182
Executor for parallel execution. Uses a simple thread pool.
Definition: transwarp.h:1344
The wait_any type. Used for tag dispatch.
Definition: transwarp.h:126
TaskType task_type
The task type.
Definition: transwarp.h:1919
void set_priority_all(std::size_t priority) override
Sets a priority to all tasks (defaults to 0). transwarp will not directly use this. This is only useful if something else is using the priority (e.g. a custom executor)
Definition: transwarp.h:1429
void schedule(bool reset) override
Schedules this task for execution on the caller thread. The task-specific executor gets precedence if...
Definition: transwarp.h:1548
virtual std::string get_name() const =0
Is supposed to return the name of the executor.
auto then(TaskType_, Functor_ &&functor) const -> decltype(std::make_shared< transwarp::task_impl< TaskType_, typename std::decay< Functor_ >::type, result_type >>(std::forward< Functor_ >(functor), std::dynamic_pointer_cast< transwarp::task< result_type >>(const_cast< task_impl * >(this) ->shared_from_this())))
Creates a continuation to this task. Overload for omitting for task name.
Definition: transwarp.h:2159
std::string to_string(const transwarp::task_type &type)
String conversion for the task_type enumeration.
Definition: transwarp.h:87
virtual void execute(const std::function< void()> &functor, const std::shared_ptr< transwarp::node > &node)=0
Is supposed to run a task which is wrapped by the functor. The functor only captures two smart pointe...
void execute(const std::function< void()> &functor, const std::shared_ptr< transwarp::node > &) override
Runs the functor on the current thread.
Definition: transwarp.h:1337
void remove_executor() override
Removes the executor from this task.
Definition: transwarp.h:1407
The accept_any type. Used for tag dispatch.
Definition: transwarp.h:110
transwarp::task_type get_type() const noexcept
The task type.
Definition: transwarp.h:167
virtual void handle_event(transwarp::event_type event, const std::shared_ptr< transwarp::node > &node)=0
This may be called from arbitrary threads depending on the event type (see transwarp::event_type) ...
bool is_ready() const override
Returns true because a value task is always ready.
Definition: transwarp.h:2370
constexpr transwarp::wait_type wait
The wait task tag.
Definition: transwarp.h:123
The root type. Used for tag dispatch.
Definition: transwarp.h:102
The task's functor consumes the first parent result that becomes ready.
A task representing a piece of work given by functor and parent tasks. By connecting tasks a directed...
Definition: transwarp.h:2109
void remove_listener(transwarp::event_type, const std::shared_ptr< transwarp::listener > &) override
No-op because a value task doesn't raise events.
Definition: transwarp.h:2302
The wait type. Used for tag dispatch.
Definition: transwarp.h:122
void cancel(bool enabled) noexceptoverride
If enabled then this task is canceled which will throw transwarp::task_canceled when retrieving the t...
Definition: transwarp.h:1689
Schedules using the given executor.
Definition: transwarp.h:1020
Result call(std::size_t node_id, const Task &task, const std::tuple< std::shared_ptr< transwarp::task< ParentResults >>...> &parents)
Calls the functor of the given task with the results from the tuple of parents. Throws transwarp::tas...
Definition: transwarp.h:911
constexpr transwarp::root_type root
The root task tag.
Definition: transwarp.h:103
void remove_custom_data() override
Removes custom data from this task.
Definition: transwarp.h:2273
void set_value(typename transwarp::decay< result_type >::type &&value) override
Assigns a value to this task. Scheduling will have no effect after a value has been set...
Definition: transwarp.h:1932
void schedule_all(transwarp::executor &executor) override
Schedules all tasks in the graph for execution using the provided executor. The task-specific executo...
Definition: transwarp.h:1581
static Result work(std::size_t node_id, const Task &task, const std::tuple< std::shared_ptr< transwarp::task< ParentResults >>...> &parents)
Definition: transwarp.h:838
schedule_type
Determines in which order tasks are scheduled in the graph.
Definition: transwarp.h:319
The task's functor accepts all parent futures.
Applies final bookkeeping to the task.
Definition: transwarp.h:993
void remove_executor_all() override
No-op because a value task never runs and doesn't have parents.
Definition: transwarp.h:2233
void schedule(transwarp::executor &executor, bool reset) override
Schedules this task for execution using the provided executor. The task-specific executor gets preced...
Definition: transwarp.h:1565
std::vector< transwarp::edge > get_graph() const override
Returns an empty graph because a value task doesn't have parents.
Definition: transwarp.h:2397
const std::shared_ptr< transwarp::node > & get_node() const noexceptoverride
Returns the associated node.
Definition: transwarp.h:1485
task_type
The possible task types.
Definition: transwarp.h:30
void set_value() override
Assigns a value to this task. Scheduling will have no effect after a call to this. Calling reset() will reset this and re-enable scheduling.
Definition: transwarp.h:2058
event_type
The task events that can be subscribed to using the below listener interface.
Definition: transwarp.h:298
The task's functor takes no arguments but waits for the first parent to finish.
Exception thrown when an invalid parameter was passed to a function.
Definition: transwarp.h:69
void remove_custom_data_all() override
Removes custom data from all tasks.
Definition: transwarp.h:1473
auto make_task(TaskType, std::string name, Functor &&functor, std::shared_ptr< Parents >...parents) -> decltype(std::make_shared< transwarp::task_impl< TaskType, typename std::decay< Functor >::type, typename Parents::result_type...>>(std::move(name), std::forward< Functor >(functor), std::move(parents)...))
A factory function to create a new task.
Definition: transwarp.h:2442
void reset() override
No-op because a value task never runs.
Definition: transwarp.h:2385
std::shared_future< void > make_ready_future()
Returns a ready future.
Definition: transwarp.h:1264
void set_executor_all(std::shared_ptr< transwarp::executor >) override
No-op because a value task never runs and doesn't have parents.
Definition: transwarp.h:2227
constexpr transwarp::accept_any_type accept_any
The accept_any task tag.
Definition: transwarp.h:111
const std::shared_future< result_type > & get_future() const noexceptoverride
Returns the future associated to the underlying execution.
Definition: transwarp.h:2283
Cancels or resumes the given task.
Definition: transwarp.h:1042
void remove_executor() override
No-op because a value task never runs.
Definition: transwarp.h:2230
void schedule(bool) override
No-op because a value task never runs.
Definition: transwarp.h:2317
void schedule_all(bool) override
No-op because a value task never runs and doesn't have parents.
Definition: transwarp.h:2329
Visits the given task using the visitor given in the constructor.
Definition: transwarp.h:1126
Pushes the given task into the vector of tasks.
Definition: transwarp.h:1114
Executor for sequential execution. Runs functors sequentially on the same thread. ...
Definition: transwarp.h:1320
auto then(TaskType_, std::string name, Functor_ &&functor) const -> decltype(std::make_shared< transwarp::task_impl< TaskType_, typename std::decay< Functor_ >::type, result_type >>(std::move(name), std::forward< Functor_ >(functor), std::dynamic_pointer_cast< transwarp::task< result_type >>(const_cast< value_task * >(this) ->shared_from_this())))
Creates a continuation to this task.
Definition: transwarp.h:2211
bool has_result() const noexceptoverride
Returns true because a value task always contains a result.
Definition: transwarp.h:2375
std::shared_future< ResultType > make_future_with_exception(std::exception_ptr exception)
Returns a ready future with the given exception as its state.
Definition: transwarp.h:1272
void remove_executor_all() override
Removes the executor from all tasks.
Definition: transwarp.h:1414
const std::shared_ptr< transwarp::node > & get_node() const noexceptoverride
Returns the associated node.
Definition: transwarp.h:2288
bool is_ready() const override
Returns whether the task has finished processing. Should only be called if was_scheduled() is true...
Definition: transwarp.h:1661
task_impl(F &&functor, std::shared_ptr< transwarp::task< ParentResults >>...parents)
This overload is for omitting the task name Note: A task must be created using shared_ptr (because of...
Definition: transwarp.h:2130
auto then(TaskType_, std::string name, Functor_ &&functor) const -> decltype(std::make_shared< transwarp::task_impl< TaskType_, typename std::decay< Functor_ >::type, result_type >>(std::move(name), std::forward< Functor_ >(functor), std::dynamic_pointer_cast< transwarp::task< result_type >>(const_cast< task_impl * >(this) ->shared_from_this())))
Creates a continuation to this task.
Definition: transwarp.h:2152
An interface for the task class.
Definition: transwarp.h:326