44inline constexpr std::array<TaskType, 7> TASK_TYPES = {
78 default: val =
"undefined";
break;
141 std::same_as<std::invoke_result_t<C>,
void>;
221 std::same_as<std::invoke_result_t<C, tf::Subflow&>,
void>;
304 (std::invocable<C, tf::Runtime&> &&
305 std::same_as<std::invoke_result_t<C, tf::Runtime&>,
void>) ||
306 (std::invocable<C, tf::NonpreemptiveRuntime&> &&
307 std::same_as<std::invoke_result_t<C, tf::NonpreemptiveRuntime&>,
void>);
398 std::convertible_to<std::invoke_result_t<C>,
int>;
571 friend class FlowBuilder;
572 friend class Runtime;
573 friend class NonpreemptiveRuntime;
574 friend class Taskflow;
575 friend class TaskView;
576 friend class Executor;
663 const std::string&
name()
const;
787 template <
typename C>
807 template <GraphLike T>
852 template <
typename... Ts>
874 template <
typename... Ts>
904 template <
typename... Ts>
934 template <
typename... Ts>
951 template <
typename I>
968 template <
typename I>
1121 template <
typename V>
1145 template <
typename V>
1168 template <
typename V>
1208 void dump(std::ostream& ostream)
const;
1292 Node* _node {
nullptr};
1296inline Task::Task(Node* node) : _node {node} {
1304template <
typename... Ts>
1306 (_node->_precede(tasks._node), ...);
1312template <
typename... Ts>
1314 (tasks._node->_precede(_node), ...);
1320template <
typename... Ts>
1322 (tasks._node->_remove_successors(_node), ...);
1323 (_node->_remove_predecessors(tasks._node), ...);
1328template <
typename... Ts>
1330 (_node->_remove_successors(tasks._node), ...);
1331 (tasks._node->_remove_predecessors(_node), ...);
1336template <GraphLike T>
1344 _node->_handle.emplace<Node::AdoptedModule>(std::move(graph));
1362 return _node == rhs._node;
1367 return _node != rhs._node;
1372 _node->_name =
name;
1378 if(!_node->_semaphores) {
1379 _node->_semaphores = std::make_unique<Node::Semaphores>();
1381 _node->_semaphores->to_acquire.push_back(&s);
1386template <
typename I>
1388 if(!_node->_semaphores) {
1389 _node->_semaphores = std::make_unique<Node::Semaphores>();
1391 _node->_semaphores->to_acquire.reserve(
1392 _node->_semaphores->to_acquire.size() + std::distance(first, last)
1394 for(
auto s = first; s != last; ++s){
1395 _node->_semaphores->to_acquire.push_back(&(*s));
1402 if(!_node->_semaphores) {
1403 _node->_semaphores = std::make_unique<Node::Semaphores>();
1405 _node->_semaphores->to_release.push_back(&s);
1410template <
typename I>
1412 if(!_node->_semaphores) {
1413 _node->_semaphores = std::make_unique<Node::Semaphores>();
1415 _node->_semaphores->to_release.reserve(
1416 _node->_semaphores->to_release.size() + std::distance(first, last)
1418 for(
auto s = first; s != last; ++s) {
1419 _node->_semaphores->to_release.push_back(&(*s));
1431 _node->_handle.emplace<std::monostate>();
1436 return _node->_name;
1446 return _node->num_strong_dependencies();
1451 return _node->num_weak_dependencies();
1456 return _node->num_successors();
1461 return _node ==
nullptr;
1466 return _node ? _node->_handle.index() != 0 :
false;
1471 return _node ? _node->_exception_ptr :
nullptr;
1476 return _node ? (_node->_exception_ptr !=
nullptr) :
false;
1481 switch(_node->_handle.index()) {
1498template <
typename V>
1500 for(
size_t i=0; i<_node->_num_successors; ++i) {
1501 visitor(
Task(_node->_edges[i]));
1506template <
typename V>
1508 for(
size_t i=_node->_num_successors; i<_node->_edges.size(); ++i) {
1509 visitor(
Task(_node->_edges[i]));
1514template <
typename V>
1516 if(
auto ptr = std::get_if<Node::Subflow>(&_node->_handle); ptr) {
1517 for(
auto itr = ptr->subgraph.begin(); itr != ptr->subgraph.end(); ++itr) {
1518 visitor(
Task(*itr));
1525 return std::hash<Node*>{}(_node);
1537template <
typename C>
1541 _node->_handle.emplace<Node::Static>(std::forward<C>(c));
1544 _node->_handle.emplace<Node::Runtime>(std::forward<C>(c));
1547 _node->_handle.emplace<Node::Subflow>(std::forward<C>(c));
1550 _node->_handle.emplace<Node::Condition>(std::forward<C>(c));
1553 _node->_handle.emplace<Node::MultiCondition>(std::forward<C>(c));
1556 static_assert(dependent_false_v<C>,
"invalid task callable");
1563 return _node->_data;
1568 _node->_data =
data;
1575#ifdef TF_ENABLE_TASK_PRIORITY
1586#ifdef TF_ENABLE_TASK_PRIORITY
1587 _node->_set_priority(p);
1615 friend class Executor;
1622 const std::string&
name()
const;
1652 template <
typename V>
1663 template <
typename V>
1678 TaskView(
const Node&);
1679 TaskView(
const TaskView&) =
default;
1685inline TaskView::TaskView(
const Node& node) : _node {node} {
1695 return _node.num_predecessors();
1700 return _node.num_strong_dependencies();
1705 return _node.num_weak_dependencies();
1710 return _node.num_successors();
1715 switch(_node._handle.index()) {
1733 return std::hash<const Node*>{}(&_node);
1737template <
typename V>
1739 for(
size_t i=0; i<_node._num_successors; ++i) {
1740 visitor(TaskView(*_node._edges[i]));
1748template <
typename V>
1750 for(
size_t i=_node._num_successors; i<_node._edges.size(); ++i) {
1751 visitor(TaskView(*_node._edges[i]));
1814 auto operator() (
const tf::Task& task)
const noexcept {
1815 return task.hash_value();
1875struct hash<
tf::TaskView> {
1876 auto operator() (
const tf::TaskView& task_view)
const noexcept {
class to create a graph object
Definition graph.hpp:47
class to create a semophore object for building a concurrency constraint
Definition semaphore.hpp:68
class to define a vector optimized for small array
Definition small_vector.hpp:931
class to access task information from the observer interface
Definition task.hpp:1613
size_t num_predecessors() const
queries the number of predecessors of the task
Definition task.hpp:1694
void for_each_predecessor(V &&visitor) const
applies an visitor callable to each predecessor of the task
Definition task.hpp:1749
void for_each_successor(V &&visitor) const
applies an visitor callable to each successor of the task
Definition task.hpp:1738
TaskType type() const
queries the task type
Definition task.hpp:1714
size_t num_weak_dependencies() const
queries the number of weak dependencies of the task
Definition task.hpp:1704
size_t hash_value() const
obtains a hash value of the underlying node
Definition task.hpp:1732
const std::string & name() const
queries the name of the task
Definition task.hpp:1689
size_t num_strong_dependencies() const
queries the number of strong dependencies of the task
Definition task.hpp:1699
size_t num_successors() const
queries the number of successors of the task
Definition task.hpp:1709
class to create a task handle over a taskflow node
Definition task.hpp:569
Task & acquire(Semaphore &semaphore)
makes the task acquire the given semaphore
Definition task.hpp:1377
const std::string & name() const
queries the name of the task
Definition task.hpp:1435
size_t num_strong_dependencies() const
queries the number of strong dependencies of the task
Definition task.hpp:1445
Task & remove_successors(Ts &&... tasks)
removes successor links from this to other tasks
Definition task.hpp:1329
size_t num_successors() const
queries the number of successors of the task
Definition task.hpp:1455
size_t hash_value() const
obtains a hash value of the underlying node
Definition task.hpp:1524
void for_each_subflow_task(V &&visitor) const
applies an visitor callable to each subflow task
Definition task.hpp:1515
Task & release(Semaphore &semaphore)
makes the task release the given semaphore
Definition task.hpp:1401
Task & work(C &&callable)
assigns a callable
Definition task.hpp:1538
std::exception_ptr exception_ptr() const
retrieves the exception pointer of this task
Definition task.hpp:1470
void reset()
resets the task handle to null
Definition task.hpp:1425
void for_each_predecessor(V &&visitor) const
applies an visitor callable to each predecessor of the task
Definition task.hpp:1507
void * data() const
queries pointer to user data
Definition task.hpp:1562
void dump(std::ostream &ostream) const
dumps the task through an output stream
Definition task.hpp:1529
Task & succeed(Ts &&... tasks)
adds precedence links from other tasks to this
Definition task.hpp:1313
Task & operator=(const Task &other)
replaces the contents with a copy of the other task
Definition task.hpp:1349
Task()=default
constructs an empty task
bool empty() const
queries if the task handle is associated with a taskflow node
Definition task.hpp:1460
Task & precede(Ts &&... tasks)
adds precedence links from this to other tasks
Definition task.hpp:1305
bool has_exception_ptr() const
queries if the task has an exception pointer
Definition task.hpp:1475
Task & adopt(tf::Graph &&graph)
creates a module task from a graph by taking over its ownership
Definition task.hpp:1343
Task & composed_of(T &object)
creates a module task from a taskflow
Definition task.hpp:1337
TaskPriority priority() const
queries the priority level of the task
Definition task.hpp:1574
Task & remove_predecessors(Ts &&... tasks)
removes predecessor links from other tasks to this
Definition task.hpp:1321
size_t num_weak_dependencies() const
queries the number of weak dependencies of the task
Definition task.hpp:1450
bool operator==(const Task &rhs) const
compares if two tasks are associated with the same taskflow node
Definition task.hpp:1361
size_t num_predecessors() const
queries the number of predecessors of the task
Definition task.hpp:1440
void reset_work()
resets the associated work to a placeholder
Definition task.hpp:1430
TaskType type() const
returns the task type
Definition task.hpp:1480
bool operator!=(const Task &rhs) const
compares if two tasks are not associated with the same taskflow node
Definition task.hpp:1366
bool has_work() const
queries if the task has a work assigned
Definition task.hpp:1465
Task & data(void *data)
assigns pointer to user data
Definition task.hpp:1567
void for_each_successor(V &&visitor) const
applies an visitor callable to each successor of the task
Definition task.hpp:1499
concept to check if a callable is a condition task
Definition task.hpp:397
determines if a callable is a multi-condition task
Definition task.hpp:494
concept to check if a callable is a static task
Definition task.hpp:140
concept to check if a callable is a subflow task
Definition task.hpp:220
taskflow namespace
Definition small_vector.hpp:20
constexpr bool is_condition_task_v
concept to check if a callable is a condition task (variable template)
Definition task.hpp:408
constexpr bool is_static_task_v
concept to check if a callable is a static task (variable template)
Definition task.hpp:151
TaskType
enumeration of all task types
Definition task.hpp:21
@ UNDEFINED
undefined task type (for internal use only)
Definition task.hpp:37
@ MODULE
module task type
Definition task.hpp:33
@ SUBFLOW
dynamic (subflow) task type
Definition task.hpp:29
@ CONDITION
condition task type
Definition task.hpp:31
@ ASYNC
asynchronous task type
Definition task.hpp:35
@ PLACEHOLDER
placeholder task type
Definition task.hpp:23
@ RUNTIME
runtime task type
Definition task.hpp:27
@ STATIC
static task type
Definition task.hpp:25
const char * to_string(TaskType type)
convert a task type to a human-readable string
Definition task.hpp:66
constexpr bool is_multi_condition_task_v
concept to check if a callable is a multi-condition task (variable template)
Definition task.hpp:505
Graph & retrieve_graph(T &target)
retrieves a reference to the underlying tf::Graph from an object
Definition graph.hpp:1108
TaskPriority
enumeration of all task priority levels
Definition graph.hpp:152
@ HIGH
the highest task priority level (most urgent)
Definition graph.hpp:154
std::ostream & operator<<(std::ostream &os, const Task &task)
overload of ostream inserter operator for Task
Definition task.hpp:1599
constexpr bool is_subflow_task_v
concept to check if a callable is a subflow task (variable template)
Definition task.hpp:231
constexpr bool is_runtime_task_v
concept to check if a callable is a runtime task (variable template)
Definition task.hpp:317
hash specialization for std::hash<tf::Task>