| Taskflow: A General-purpose Task-parallel Programming System

Loading...
Searching...
No Matches
task.hpp
1#pragma once
2
3#include "graph.hpp"
4
9
10 namespace tf {
11
12// ----------------------------------------------------------------------------
13// Task Types
14// ----------------------------------------------------------------------------
15
21 enum class TaskType : int {
23 PLACEHOLDER = 0,
25 STATIC,
27 RUNTIME,
29 SUBFLOW,
31 CONDITION,
33 MODULE,
35 ASYNC,
37 UNDEFINED
38};
39
44 inline constexpr std::array<TaskType, 7> TASK_TYPES = {
45 TaskType::PLACEHOLDER,
46 TaskType::STATIC,
47 TaskType::RUNTIME,
48 TaskType::SUBFLOW,
49 TaskType::CONDITION,
50 TaskType::MODULE,
51 TaskType::ASYNC,
52};
53
66 inline const char* to_string(TaskType type) {
67
68 const char* val;
69
70 switch(type) {
71 case TaskType::PLACEHOLDER: val = "placeholder"; break;
72 case TaskType::STATIC: val = "static"; break;
73 case TaskType::RUNTIME: val = "runtime"; break;
74 case TaskType::SUBFLOW: val = "subflow"; break;
75 case TaskType::CONDITION: val = "condition"; break;
76 case TaskType::MODULE: val = "module"; break;
77 case TaskType::ASYNC: val = "async"; break;
78 default: val = "undefined"; break;
79 }
80
81 return val;
82}
83
84// ----------------------------------------------------------------------------
85// Static Task Trait
86// ----------------------------------------------------------------------------
87
139 template <typename C>
140 concept StaticTaskLike = std::invocable<C> &&
141 std::same_as<std::invoke_result_t<C>, void>;
142
150 template <typename C>
151 constexpr bool is_static_task_v = StaticTaskLike<C>;
152
153// ----------------------------------------------------------------------------
154// Subflow Task Trait
155// ----------------------------------------------------------------------------
156
219 template <typename C>
220 concept SubflowTaskLike = std::invocable<C, tf::Subflow&> &&
221 std::same_as<std::invoke_result_t<C, tf::Subflow&>, void>;
222
230 template <typename C>
231 constexpr bool is_subflow_task_v = SubflowTaskLike<C>;
232
233// ----------------------------------------------------------------------------
234// Runtime Task Trait
235// ----------------------------------------------------------------------------
236
302 template <typename C>
303 concept RuntimeTaskLike =
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>);
308
316 template <typename C>
317 constexpr bool is_runtime_task_v = RuntimeTaskLike<C>;
318
319
320// ----------------------------------------------------------------------------
321// Condition Task Trait
322// ----------------------------------------------------------------------------
323
396 template <typename C>
397 concept ConditionTaskLike = std::invocable<C> &&
398 std::convertible_to<std::invoke_result_t<C>, int>;
399
407 template <typename C>
408 constexpr bool is_condition_task_v = ConditionTaskLike<C>;
409
493 template <typename C>
494 concept MultiConditionTaskLike = std::invocable<C> &&
495 std::same_as<std::invoke_result_t<C>, SmallVector<int>>;
496
504 template <typename C>
505 constexpr bool is_multi_condition_task_v = MultiConditionTaskLike<C>;
506
507
508// ----------------------------------------------------------------------------
509// Task
510// ----------------------------------------------------------------------------
511
569 class Task {
570
571 friend class FlowBuilder;
572 friend class Runtime;
573 friend class NonpreemptiveRuntime;
574 friend class Taskflow;
575 friend class TaskView;
576 friend class Executor;
577
578 public:
579
585 Task() = default;
586
599 Task(const Task& other);
600
612 Task& operator = (const Task& other);
613
622 Task& operator = (std::nullptr_t);
623
636 bool operator == (const Task& rhs) const;
637
650 bool operator != (const Task& rhs) const;
651
663 const std::string& name() const;
664
677 size_t num_successors() const;
678
691 size_t num_predecessors() const;
692
720 size_t num_strong_dependencies() const;
721
749 size_t num_weak_dependencies() const;
750
763 Task& name(const std::string& name);
764
787 template <typename C>
788 Task& work(C&& callable);
789
807 template <GraphLike T>
808 Task& composed_of(T& object);
809
831 Task& adopt(tf::Graph&& graph);
832
852 template <typename... Ts>
853 Task& precede(Ts&&... tasks);
854
874 template <typename... Ts>
875 Task& succeed(Ts&&... tasks);
876
904 template <typename... Ts>
905 Task& remove_predecessors(Ts&&... tasks);
906
934 template <typename... Ts>
935 Task& remove_successors(Ts&&... tasks);
936
943 Task& release(Semaphore& semaphore);
944
951 template <typename I>
952 Task& release(I first, I last);
953
960 Task& acquire(Semaphore& semaphore);
961
968 template <typename I>
969 Task& acquire(I first, I last);
970
1000 Task& data(void* data);
1001
1002
1030 Task& priority(TaskPriority p);
1031
1047 TaskPriority priority() const;
1048
1061 void reset();
1062
1066 void reset_work();
1067
1082 bool empty() const;
1083
1097 bool has_work() const;
1098
1121 template <typename V>
1122 void for_each_successor(V&& visitor) const;
1123
1145 template <typename V>
1146 void for_each_predecessor(V&& visitor) const;
1147
1168 template <typename V>
1169 void for_each_subflow_task(V&& visitor) const;
1170
1183 size_t hash_value() const;
1184
1197 TaskType type() const;
1198
1208 void dump(std::ostream& ostream) const;
1209
1237 void* data() const;
1238
1279 std::exception_ptr exception_ptr() const;
1280
1286 bool has_exception_ptr() const;
1287
1288 private:
1289
1290 Task(Node*);
1291
1292 Node* _node {nullptr};
1293};
1294
1295// Constructor
1296 inline Task::Task(Node* node) : _node {node} {
1297}
1298
1299// Constructor
1300 inline Task::Task(const Task& rhs) : _node {rhs._node} {
1301}
1302
1303// Function: precede
1304 template <typename... Ts>
1305 Task& Task::precede(Ts&&... tasks) {
1306 (_node->_precede(tasks._node), ...);
1307 //_precede(std::forward<Ts>(tasks)...);
1308 return *this;
1309}
1310
1311// Function: succeed
1312 template <typename... Ts>
1313 Task& Task::succeed(Ts&&... tasks) {
1314 (tasks._node->_precede(_node), ...);
1315 //_succeed(std::forward<Ts>(tasks)...);
1316 return *this;
1317}
1318
1319// Function: remove_predecessors
1320 template <typename... Ts>
1321 Task& Task::remove_predecessors(Ts&&... tasks) {
1322 (tasks._node->_remove_successors(_node), ...);
1323 (_node->_remove_predecessors(tasks._node), ...);
1324 return *this;
1325}
1326
1327// Function: remove_successors
1328 template <typename... Ts>
1329 Task& Task::remove_successors(Ts&&... tasks) {
1330 (_node->_remove_successors(tasks._node), ...);
1331 (tasks._node->_remove_predecessors(_node), ...);
1332 return *this;
1333}
1334
1335// Function: composed_of
1336 template <GraphLike T>
1337 Task& Task::composed_of(T& target) {
1338 _node->_handle.emplace<Node::Module>(retrieve_graph(target));
1339 return *this;
1340}
1341
1342// Function: adopt
1343 inline Task& Task::adopt(Graph&& graph) {
1344 _node->_handle.emplace<Node::AdoptedModule>(std::move(graph));
1345 return *this;
1346}
1347
1348// Operator =
1349 inline Task& Task::operator = (const Task& rhs) {
1350 _node = rhs._node;
1351 return *this;
1352}
1353
1354// Operator =
1355 inline Task& Task::operator = (std::nullptr_t ptr) {
1356 _node = ptr;
1357 return *this;
1358}
1359
1360// Operator ==
1361 inline bool Task::operator == (const Task& rhs) const {
1362 return _node == rhs._node;
1363}
1364
1365// Operator !=
1366 inline bool Task::operator != (const Task& rhs) const {
1367 return _node != rhs._node;
1368}
1369
1370// Function: name
1371 inline Task& Task::name(const std::string& name) {
1372 _node->_name = name;
1373 return *this;
1374}
1375
1376// Function: acquire
1377 inline Task& Task::acquire(Semaphore& s) {
1378 if(!_node->_semaphores) {
1379 _node->_semaphores = std::make_unique<Node::Semaphores>();
1380 }
1381 _node->_semaphores->to_acquire.push_back(&s);
1382 return *this;
1383}
1384
1385// Function: acquire
1386 template <typename I>
1387 Task& Task::acquire(I first, I last) {
1388 if(!_node->_semaphores) {
1389 _node->_semaphores = std::make_unique<Node::Semaphores>();
1390 }
1391 _node->_semaphores->to_acquire.reserve(
1392 _node->_semaphores->to_acquire.size() + std::distance(first, last)
1393 );
1394 for(auto s = first; s != last; ++s){
1395 _node->_semaphores->to_acquire.push_back(&(*s));
1396 }
1397 return *this;
1398}
1399
1400// Function: release
1401 inline Task& Task::release(Semaphore& s) {
1402 if(!_node->_semaphores) {
1403 _node->_semaphores = std::make_unique<Node::Semaphores>();
1404 }
1405 _node->_semaphores->to_release.push_back(&s);
1406 return *this;
1407}
1408
1409// Function: release
1410 template <typename I>
1411 Task& Task::release(I first, I last) {
1412 if(!_node->_semaphores) {
1413 _node->_semaphores = std::make_unique<Node::Semaphores>();
1414 }
1415 _node->_semaphores->to_release.reserve(
1416 _node->_semaphores->to_release.size() + std::distance(first, last)
1417 );
1418 for(auto s = first; s != last; ++s) {
1419 _node->_semaphores->to_release.push_back(&(*s));
1420 }
1421 return *this;
1422}
1423
1424// Procedure: reset
1425 inline void Task::reset() {
1426 _node = nullptr;
1427}
1428
1429// Procedure: reset_work
1430 inline void Task::reset_work() {
1431 _node->_handle.emplace<std::monostate>();
1432}
1433
1434// Function: name
1435 inline const std::string& Task::name() const {
1436 return _node->_name;
1437}
1438
1439// Function: num_predecessors
1440 inline size_t Task::num_predecessors() const {
1441 return _node->num_predecessors();
1442}
1443
1444// Function: num_strong_dependencies
1445 inline size_t Task::num_strong_dependencies() const {
1446 return _node->num_strong_dependencies();
1447}
1448
1449// Function: num_weak_dependencies
1450 inline size_t Task::num_weak_dependencies() const {
1451 return _node->num_weak_dependencies();
1452}
1453
1454// Function: num_successors
1455 inline size_t Task::num_successors() const {
1456 return _node->num_successors();
1457}
1458
1459// Function: empty
1460 inline bool Task::empty() const {
1461 return _node == nullptr;
1462}
1463
1464// Function: has_work
1465 inline bool Task::has_work() const {
1466 return _node ? _node->_handle.index() != 0 : false;
1467}
1468
1469// Function: exception
1470 inline std::exception_ptr Task::exception_ptr() const {
1471 return _node ? _node->_exception_ptr : nullptr;
1472}
1473
1474// Function: has_exception
1475 inline bool Task::has_exception_ptr() const {
1476 return _node ? (_node->_exception_ptr != nullptr) : false;
1477}
1478
1479// Function: task_type
1480 inline TaskType Task::type() const {
1481 switch(_node->_handle.index()) {
1482 case Node::PLACEHOLDER: return TaskType::PLACEHOLDER;
1483 case Node::STATIC: return TaskType::STATIC;
1484 case Node::RUNTIME: return TaskType::RUNTIME;
1485 case Node::NONPREEMPTIVE_RUNTIME: return TaskType::RUNTIME;
1486 case Node::SUBFLOW: return TaskType::SUBFLOW;
1487 case Node::CONDITION: return TaskType::CONDITION;
1488 case Node::MULTI_CONDITION: return TaskType::CONDITION;
1489 case Node::MODULE: return TaskType::MODULE;
1490 case Node::ADOPTED_MODULE: return TaskType::MODULE;
1491 case Node::ASYNC: return TaskType::ASYNC;
1492 case Node::DEPENDENT_ASYNC: return TaskType::ASYNC;
1493 default: return TaskType::UNDEFINED;
1494 }
1495}
1496
1497// Function: for_each_successor
1498 template <typename V>
1499 void Task::for_each_successor(V&& visitor) const {
1500 for(size_t i=0; i<_node->_num_successors; ++i) {
1501 visitor(Task(_node->_edges[i]));
1502 }
1503}
1504
1505// Function: for_each_predecessor
1506 template <typename V>
1507 void Task::for_each_predecessor(V&& visitor) const {
1508 for(size_t i=_node->_num_successors; i<_node->_edges.size(); ++i) {
1509 visitor(Task(_node->_edges[i]));
1510 }
1511}
1512
1513// Function: for_each_subflow_task
1514 template <typename V>
1515 void Task::for_each_subflow_task(V&& visitor) const {
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));
1519 }
1520 }
1521}
1522
1523// Function: hash_value
1524 inline size_t Task::hash_value() const {
1525 return std::hash<Node*>{}(_node);
1526}
1527
1528// Procedure: dump
1529 inline void Task::dump(std::ostream& os) const {
1530 os << "task ";
1531 if(name().empty()) os << _node;
1532 else os << name();
1533 os << " [type=" << to_string(type()) << ']';
1534}
1535
1536// Function: work
1537 template <typename C>
1538 Task& Task::work(C&& c) {
1539
1540 if constexpr(is_static_task_v<C>) {
1541 _node->_handle.emplace<Node::Static>(std::forward<C>(c));
1542 }
1543 else if constexpr(is_runtime_task_v<C>) {
1544 _node->_handle.emplace<Node::Runtime>(std::forward<C>(c));
1545 }
1546 else if constexpr(is_subflow_task_v<C>) {
1547 _node->_handle.emplace<Node::Subflow>(std::forward<C>(c));
1548 }
1549 else if constexpr(is_condition_task_v<C>) {
1550 _node->_handle.emplace<Node::Condition>(std::forward<C>(c));
1551 }
1552 else if constexpr(is_multi_condition_task_v<C>) {
1553 _node->_handle.emplace<Node::MultiCondition>(std::forward<C>(c));
1554 }
1555 else {
1556 static_assert(dependent_false_v<C>, "invalid task callable");
1557 }
1558 return *this;
1559}
1560
1561// Function: data
1562 inline void* Task::data() const {
1563 return _node->_data;
1564}
1565
1566// Function: data
1567 inline Task& Task::data(void* data) {
1568 _node->_data = data;
1569 return *this;
1570}
1571
1572
1573// Function: priority
1574 inline TaskPriority Task::priority() const {
1575#ifdef TF_ENABLE_TASK_PRIORITY
1576 // priority bits are stored directly as the TaskPriority value
1577 // (HIGH=0, NORMAL=1, LOW=2); an unset priority reads back as HIGH
1578 return static_cast<TaskPriority>(_node->priority());
1579#else
1580 return TaskPriority::HIGH;
1581#endif
1582}
1583
1584// Function: priority
1585 inline Task& Task::priority([[maybe_unused]] TaskPriority p) {
1586#ifdef TF_ENABLE_TASK_PRIORITY
1587 _node->_set_priority(p);
1588#endif
1589 return *this;
1590}
1591
1592// ----------------------------------------------------------------------------
1593// global ostream
1594// ----------------------------------------------------------------------------
1595
1599 inline std::ostream& operator << (std::ostream& os, const Task& task) {
1600 task.dump(os);
1601 return os;
1602}
1603
1604// ----------------------------------------------------------------------------
1605// Task View
1606// ----------------------------------------------------------------------------
1607
1613 class TaskView {
1614
1615 friend class Executor;
1616
1617 public:
1618
1622 const std::string& name() const;
1623
1627 size_t num_successors() const;
1628
1632 size_t num_predecessors() const;
1633
1637 size_t num_strong_dependencies() const;
1638
1642 size_t num_weak_dependencies() const;
1643
1652 template <typename V>
1653 void for_each_successor(V&& visitor) const;
1654
1663 template <typename V>
1664 void for_each_predecessor(V&& visitor) const;
1665
1669 TaskType type() const;
1670
1674 size_t hash_value() const;
1675
1676 private:
1677
1678 TaskView(const Node&);
1679 TaskView(const TaskView&) = default;
1680
1681 const Node& _node;
1682};
1683
1684// Constructor
1685 inline TaskView::TaskView(const Node& node) : _node {node} {
1686}
1687
1688// Function: name
1689 inline const std::string& TaskView::name() const {
1690 return _node._name;
1691}
1692
1693// Function: num_predecessors
1694 inline size_t TaskView::num_predecessors() const {
1695 return _node.num_predecessors();
1696}
1697
1698// Function: num_strong_dependencies
1699 inline size_t TaskView::num_strong_dependencies() const {
1700 return _node.num_strong_dependencies();
1701}
1702
1703// Function: num_weak_dependencies
1704 inline size_t TaskView::num_weak_dependencies() const {
1705 return _node.num_weak_dependencies();
1706}
1707
1708// Function: num_successors
1709 inline size_t TaskView::num_successors() const {
1710 return _node.num_successors();
1711}
1712
1713// Function: type
1714 inline TaskType TaskView::type() const {
1715 switch(_node._handle.index()) {
1716 case Node::PLACEHOLDER: return TaskType::PLACEHOLDER;
1717 case Node::STATIC: return TaskType::STATIC;
1718 case Node::RUNTIME: return TaskType::RUNTIME;
1719 case Node::NONPREEMPTIVE_RUNTIME: return TaskType::RUNTIME;
1720 case Node::SUBFLOW: return TaskType::SUBFLOW;
1721 case Node::CONDITION: return TaskType::CONDITION;
1722 case Node::MULTI_CONDITION: return TaskType::CONDITION;
1723 case Node::MODULE: return TaskType::MODULE;
1724 case Node::ADOPTED_MODULE: return TaskType::MODULE;
1725 case Node::ASYNC: return TaskType::ASYNC;
1726 case Node::DEPENDENT_ASYNC: return TaskType::ASYNC;
1727 default: return TaskType::UNDEFINED;
1728 }
1729}
1730
1731// Function: hash_value
1732 inline size_t TaskView::hash_value() const {
1733 return std::hash<const Node*>{}(&_node);
1734}
1735
1736// Function: for_each_successor
1737 template <typename V>
1738 void TaskView::for_each_successor(V&& visitor) const {
1739 for(size_t i=0; i<_node._num_successors; ++i) {
1740 visitor(TaskView(*_node._edges[i]));
1741 }
1742 //for(size_t i=0; i<_node._successors.size(); ++i) {
1743 // visitor(TaskView(*_node._successors[i]));
1744 //}
1745}
1746
1747// Function: for_each_predecessor
1748 template <typename V>
1749 void TaskView::for_each_predecessor(V&& visitor) const {
1750 for(size_t i=_node._num_successors; i<_node._edges.size(); ++i) {
1751 visitor(TaskView(*_node._edges[i]));
1752 }
1753 //for(size_t i=0; i<_node._predecessors.size(); ++i) {
1754 // visitor(TaskView(*_node._predecessors[i]));
1755 //}
1756}
1757
1758} // end of namespace tf. ----------------------------------------------------
1759
1760 namespace std {
1761
1812 template <>
1813 struct hash<tf::Task> {
1814 auto operator() (const tf::Task& task) const noexcept {
1815 return task.hash_value();
1816 }
1817};
1818
1819
1820
1874 template <>
1875 struct hash<tf::TaskView> {
1876 auto operator() (const tf::TaskView& task_view) const noexcept {
1877 return task_view.hash_value();
1878 }
1879};
1880
1881} // end of namespace std ----------------------------------------------------
tf::Graph
class to create a graph object
Definition graph.hpp:47
tf::Semaphore
class to create a semophore object for building a concurrency constraint
Definition semaphore.hpp:68
tf::SmallVector
class to define a vector optimized for small array
Definition small_vector.hpp:931
tf::TaskView
class to access task information from the observer interface
Definition task.hpp:1613
tf::TaskView::num_predecessors
size_t num_predecessors() const
queries the number of predecessors of the task
Definition task.hpp:1694
tf::TaskView::for_each_predecessor
void for_each_predecessor(V &&visitor) const
applies an visitor callable to each predecessor of the task
Definition task.hpp:1749
tf::TaskView::for_each_successor
void for_each_successor(V &&visitor) const
applies an visitor callable to each successor of the task
Definition task.hpp:1738
tf::TaskView::type
TaskType type() const
queries the task type
Definition task.hpp:1714
tf::TaskView::num_weak_dependencies
size_t num_weak_dependencies() const
queries the number of weak dependencies of the task
Definition task.hpp:1704
tf::TaskView::hash_value
size_t hash_value() const
obtains a hash value of the underlying node
Definition task.hpp:1732
tf::TaskView::name
const std::string & name() const
queries the name of the task
Definition task.hpp:1689
tf::TaskView::num_strong_dependencies
size_t num_strong_dependencies() const
queries the number of strong dependencies of the task
Definition task.hpp:1699
tf::TaskView::num_successors
size_t num_successors() const
queries the number of successors of the task
Definition task.hpp:1709
tf::Task
class to create a task handle over a taskflow node
Definition task.hpp:569
tf::Task::acquire
Task & acquire(Semaphore &semaphore)
makes the task acquire the given semaphore
Definition task.hpp:1377
tf::Task::name
const std::string & name() const
queries the name of the task
Definition task.hpp:1435
tf::Task::num_strong_dependencies
size_t num_strong_dependencies() const
queries the number of strong dependencies of the task
Definition task.hpp:1445
tf::Task::remove_successors
Task & remove_successors(Ts &&... tasks)
removes successor links from this to other tasks
Definition task.hpp:1329
tf::Task::num_successors
size_t num_successors() const
queries the number of successors of the task
Definition task.hpp:1455
tf::Task::hash_value
size_t hash_value() const
obtains a hash value of the underlying node
Definition task.hpp:1524
tf::Task::for_each_subflow_task
void for_each_subflow_task(V &&visitor) const
applies an visitor callable to each subflow task
Definition task.hpp:1515
tf::Task::release
Task & release(Semaphore &semaphore)
makes the task release the given semaphore
Definition task.hpp:1401
tf::Task::work
Task & work(C &&callable)
assigns a callable
Definition task.hpp:1538
tf::Task::exception_ptr
std::exception_ptr exception_ptr() const
retrieves the exception pointer of this task
Definition task.hpp:1470
tf::Task::reset
void reset()
resets the task handle to null
Definition task.hpp:1425
tf::Task::for_each_predecessor
void for_each_predecessor(V &&visitor) const
applies an visitor callable to each predecessor of the task
Definition task.hpp:1507
tf::Task::data
void * data() const
queries pointer to user data
Definition task.hpp:1562
tf::Task::dump
void dump(std::ostream &ostream) const
dumps the task through an output stream
Definition task.hpp:1529
tf::Task::succeed
Task & succeed(Ts &&... tasks)
adds precedence links from other tasks to this
Definition task.hpp:1313
tf::Task::operator=
Task & operator=(const Task &other)
replaces the contents with a copy of the other task
Definition task.hpp:1349
tf::Task::Task
Task()=default
constructs an empty task
tf::Task::empty
bool empty() const
queries if the task handle is associated with a taskflow node
Definition task.hpp:1460
tf::Task::precede
Task & precede(Ts &&... tasks)
adds precedence links from this to other tasks
Definition task.hpp:1305
tf::Task::has_exception_ptr
bool has_exception_ptr() const
queries if the task has an exception pointer
Definition task.hpp:1475
tf::Task::adopt
Task & adopt(tf::Graph &&graph)
creates a module task from a graph by taking over its ownership
Definition task.hpp:1343
tf::Task::composed_of
Task & composed_of(T &object)
creates a module task from a taskflow
Definition task.hpp:1337
tf::Task::priority
TaskPriority priority() const
queries the priority level of the task
Definition task.hpp:1574
tf::Task::remove_predecessors
Task & remove_predecessors(Ts &&... tasks)
removes predecessor links from other tasks to this
Definition task.hpp:1321
tf::Task::num_weak_dependencies
size_t num_weak_dependencies() const
queries the number of weak dependencies of the task
Definition task.hpp:1450
tf::Task::operator==
bool operator==(const Task &rhs) const
compares if two tasks are associated with the same taskflow node
Definition task.hpp:1361
tf::Task::num_predecessors
size_t num_predecessors() const
queries the number of predecessors of the task
Definition task.hpp:1440
tf::Task::reset_work
void reset_work()
resets the associated work to a placeholder
Definition task.hpp:1430
tf::Task::type
TaskType type() const
returns the task type
Definition task.hpp:1480
tf::Task::operator!=
bool operator!=(const Task &rhs) const
compares if two tasks are not associated with the same taskflow node
Definition task.hpp:1366
tf::Task::has_work
bool has_work() const
queries if the task has a work assigned
Definition task.hpp:1465
tf::Task::data
Task & data(void *data)
assigns pointer to user data
Definition task.hpp:1567
tf::Task::for_each_successor
void for_each_successor(V &&visitor) const
applies an visitor callable to each successor of the task
Definition task.hpp:1499
tf::ConditionTaskLike
concept to check if a callable is a condition task
Definition task.hpp:397
tf::MultiConditionTaskLike
determines if a callable is a multi-condition task
Definition task.hpp:494
tf::RuntimeTaskLike
concept to check if a callable is a runtime task
Definition task.hpp:303
tf::StaticTaskLike
concept to check if a callable is a static task
Definition task.hpp:140
tf::SubflowTaskLike
concept to check if a callable is a subflow task
Definition task.hpp:220
tf
taskflow namespace
Definition small_vector.hpp:20
tf::is_condition_task_v
constexpr bool is_condition_task_v
concept to check if a callable is a condition task (variable template)
Definition task.hpp:408
tf::is_static_task_v
constexpr bool is_static_task_v
concept to check if a callable is a static task (variable template)
Definition task.hpp:151
tf::TaskType
TaskType
enumeration of all task types
Definition task.hpp:21
tf::TaskType::UNDEFINED
@ UNDEFINED
undefined task type (for internal use only)
Definition task.hpp:37
tf::TaskType::MODULE
@ MODULE
module task type
Definition task.hpp:33
tf::TaskType::SUBFLOW
@ SUBFLOW
dynamic (subflow) task type
Definition task.hpp:29
tf::TaskType::CONDITION
@ CONDITION
condition task type
Definition task.hpp:31
tf::TaskType::ASYNC
@ ASYNC
asynchronous task type
Definition task.hpp:35
tf::TaskType::PLACEHOLDER
@ PLACEHOLDER
placeholder task type
Definition task.hpp:23
tf::TaskType::RUNTIME
@ RUNTIME
runtime task type
Definition task.hpp:27
tf::TaskType::STATIC
@ STATIC
static task type
Definition task.hpp:25
tf::to_string
const char * to_string(TaskType type)
convert a task type to a human-readable string
Definition task.hpp:66
tf::is_multi_condition_task_v
constexpr bool is_multi_condition_task_v
concept to check if a callable is a multi-condition task (variable template)
Definition task.hpp:505
tf::retrieve_graph
Graph & retrieve_graph(T &target)
retrieves a reference to the underlying tf::Graph from an object
Definition graph.hpp:1108
tf::TaskPriority
TaskPriority
enumeration of all task priority levels
Definition graph.hpp:152
tf::TaskPriority::HIGH
@ HIGH
the highest task priority level (most urgent)
Definition graph.hpp:154
tf::operator<<
std::ostream & operator<<(std::ostream &os, const Task &task)
overload of ostream inserter operator for Task
Definition task.hpp:1599
tf::is_subflow_task_v
constexpr bool is_subflow_task_v
concept to check if a callable is a subflow task (variable template)
Definition task.hpp:231
tf::is_runtime_task_v
constexpr bool is_runtime_task_v
concept to check if a callable is a runtime task (variable template)
Definition task.hpp:317
hash
hash specialization for std::hash<tf::Task>