3#include "../utility/iterator.hpp"
4#include "../utility/object_pool.hpp"
5#include "../utility/traits.hpp"
6#include "../utility/os.hpp"
7#include "../utility/math.hpp"
8#include "../utility/small_vector.hpp"
10#include "declarations.hpp"
12#include "environment.hpp"
13#include "topology.hpp"
29class CustomGraphBase {
34 virtual ~CustomGraphBase() =
default;
116 void _clear_detached();
117 void _merge(
Graph&&);
120 template <
typename ...ArgsT>
121 Node* _emplace_back(ArgsT&&... args);
123 Node* _emplace_back();
213 template <
typename C>
226inline Runtime::Runtime(
Executor& e, Worker& w, Node* p) :
255 TF_ENABLE_POOLABLE_ON_THIS;
258 constexpr static int CONDITIONED = 1;
259 constexpr static int DETACHED = 2;
260 constexpr static int ACQUIRED = 4;
261 constexpr static int READY = 8;
262 constexpr static int DEFERRED = 16;
267 template <
typename C>
276 template <
typename C>
285 template <
typename C>
295 template <
typename C>
302 struct MultiCondition {
304 template <
typename C>
313 template <
typename T>
322 template <
typename T>
333 template <
typename C>
342 template <
typename C,
typename G>
343 cudaFlow(C&& c, G&& g);
353 template <
typename C,
typename G>
354 syclFlow(C&& c, G&& g);
376 SmallVector<Semaphore*> to_acquire;
377 SmallVector<Semaphore*> to_release;
383 constexpr static auto PLACEHOLDER = get_index_v<std::monostate, handle_t>;
384 constexpr static auto STATIC = get_index_v<Static, handle_t>;
385 constexpr static auto DYNAMIC = get_index_v<Dynamic, handle_t>;
386 constexpr static auto CONDITION = get_index_v<Condition, handle_t>;
387 constexpr static auto MULTI_CONDITION = get_index_v<MultiCondition, handle_t>;
388 constexpr static auto MODULE = get_index_v<Module, handle_t>;
389 constexpr static auto ASYNC = get_index_v<Async, handle_t>;
390 constexpr static auto SILENT_ASYNC = get_index_v<SilentAsync, handle_t>;
391 constexpr static auto CUDAFLOW = get_index_v<cudaFlow, handle_t>;
392 constexpr static auto SYCLFLOW = get_index_v<syclFlow, handle_t>;
393 constexpr static auto RUNTIME = get_index_v<Runtime, handle_t>;
395 template <
typename... Args>
396 Node(Args&&... args);
400 size_t num_successors()
const;
401 size_t num_dependents()
const;
402 size_t num_strong_dependents()
const;
403 size_t num_weak_dependents()
const;
411 void* _data {
nullptr};
415 SmallVector<Node*> _successors;
416 SmallVector<Node*> _dependents;
418 Topology* _topology {
nullptr};
420 Node* _parent {
nullptr};
427 void _precede(Node*);
428 void _set_up_join_counter();
430 bool _is_cancelled()
const;
431 bool _is_conditioner()
const;
432 bool _acquire_all(SmallVector<Node*>&);
434 SmallVector<Node*> _release_all();
444inline ObjectPool<Node> node_pool;
452Node::Static::Static(C&& c) : work {
std::
forward<C>(c)} {
461Node::Dynamic::Dynamic(C&& c) : work {
std::
forward<C>(c)} {
470Node::Condition::Condition(C&& c) : work {
std::
forward<C>(c)} {
479Node::MultiCondition::MultiCondition(C&& c) : work {
std::
forward<C>(c)} {
486template <
typename C,
typename G>
487Node::cudaFlow::cudaFlow(C&& c, G&& g) :
496template <
typename C,
typename G>
497Node::syclFlow::syclFlow(C&& c, G&& g) :
508inline Node::Module::Module(T& obj) : graph{ obj.graph() } {
528Node::SilentAsync::SilentAsync(C&& c) :
538Node::Runtime::Runtime(C&& c) :
547template <
typename... Args>
548Node::Node(Args&&... args): _handle{
std::
forward<Args>(args)...} {
552inline Node::~Node() {
555 if(_handle.index() ==
DYNAMIC) {
562 nodes.reserve(subgraph.size());
567 subgraph._nodes.clear();
571 while(i < nodes.size()) {
573 if(nodes[i]->_handle.index() ==
DYNAMIC) {
585 for(i=0; i<nodes.size(); ++i) {
586 node_pool.recycle(nodes[i]);
592inline void Node::_precede(Node* v) {
593 _successors.push_back(v);
594 v->_dependents.push_back(
this);
598inline size_t Node::num_successors()
const {
599 return _successors.size();
603inline size_t Node::num_dependents()
const {
604 return _dependents.size();
608inline size_t Node::num_weak_dependents()
const {
610 for(
size_t i=0; i<_dependents.size(); i++) {
612 if(_dependents[i]->_is_conditioner()) {
620inline size_t Node::num_strong_dependents()
const {
622 for(
size_t i=0; i<_dependents.size(); i++) {
624 if(!_dependents[i]->_is_conditioner()) {
637inline bool Node::_is_conditioner()
const {
638 return _handle.index() == Node::CONDITION ||
639 _handle.index() == Node::MULTI_CONDITION;
643inline bool Node::_is_cancelled()
const {
644 if(_handle.index() == Node::ASYNC) {
655inline void Node::_set_up_join_counter() {
657 for(
auto p : _dependents) {
659 if(p->_is_conditioner()) {
671inline bool Node::_acquire_all(SmallVector<Node*>& nodes) {
673 auto& to_acquire = _semaphores->to_acquire;
675 for(
size_t i = 0; i < to_acquire.size(); ++i) {
676 if(!to_acquire[i]->_try_acquire_or_wait(
this)) {
677 for(
size_t j = 1; j <= i; ++j) {
678 auto r = to_acquire[i-j]->_release();
688inline SmallVector<Node*> Node::_release_all() {
690 auto& to_release = _semaphores->to_release;
692 SmallVector<Node*> nodes;
693 for(
const auto& sem : to_release) {
694 auto r = sem->_release();
712 _nodes {
std::move(other._nodes)} {
728inline void Graph::_clear() {
729 for(
auto node : _nodes) {
730 node_pool.recycle(node);
736inline void Graph::_clear_detached() {
738 auto mid =
std::partition(_nodes.begin(), _nodes.end(), [] (Node* node) {
739 return !(node->_state.load(std::memory_order_relaxed) & Node::DETACHED);
742 for(
auto itr = mid; itr != _nodes.end(); ++itr) {
743 node_pool.recycle(*itr);
749inline void Graph::_merge(Graph&& g) {
750 for(
auto n : g._nodes) {
757inline void Graph::_erase(Node* node) {
758 if(
auto I =
std::find(_nodes.begin(), _nodes.end(), node); I != _nodes.end()) {
760 node_pool.recycle(node);
766 return _nodes.size();
771 return _nodes.empty();
775template <
typename ...ArgsT>
776Node* Graph::_emplace_back(ArgsT&&... args) {
778 return _nodes.back();
782inline Node* Graph::_emplace_back() {
783 _nodes.push_back(node_pool.animate());
784 return _nodes.back();
T back_inserter(T... args)
class to create an executor for running a taskflow graph
Definition executor.hpp:50
class to build a task dependency graph
Definition flow_builder.hpp:21
class to create a graph object
Definition graph.hpp:56
Graph & operator=(const Graph &)=delete
disabled copy assignment operator
Graph()=default
constructs a graph object
bool empty() const
queries if the graph is empty
Definition graph.hpp:770
~Graph()
destructs the graph object
Definition graph.hpp:706
size_t size() const
queries the number of nodes in the graph
Definition graph.hpp:765
void clear()
clears the graph
Definition graph.hpp:723
Graph(const Graph &)=delete
disabled copy constructor
class to create a runtime object used by a runtime task
Definition graph.hpp:150
Executor & executor()
obtains the running executor
Definition graph.hpp:233
void run(C &&)
runs a task callable synchronously
Definition executor.hpp:1963
void schedule(Task task)
schedules an active task immediately to the worker's queue
Definition executor.hpp:1953
class to construct a subflow graph from the execution of a dynamic task
Definition flow_builder.hpp:889
class to access task information from the observer interface
Definition task.hpp:638
class to create a task handle over a node in a taskflow graph
Definition task.hpp:187
class to create a taskflow object
Definition core/taskflow.hpp:73
taskflow namespace
Definition small_vector.hpp:27
@ DYNAMIC
dynamic (subflow) task type
@ CUDAFLOW
cudaFlow task type
@ MULTI_CONDITION
multi-condition task type
@ CONDITION
condition task type
@ SYCLFLOW
syclFlow task type
@ ASYNC
asynchronous task type
@ PLACEHOLDER
placeholder task type
@ RUNTIME
runtime task type