Back to Taskflow

Taskflow: A General

docs/graph_8hpp_source.html

4.1.035.5 KB
Original Source

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

Loading...

Searching...

No Matches

graph.hpp

1#pragma once

2

3#include "../utility/macros.hpp"

4#include "../utility/traits.hpp"

5#include "../utility/iterator.hpp"

6

7#ifdef TF_ENABLE_TASK_POOL

8#include "../utility/object_pool.hpp"

9#endif

10

11#include "../utility/os.hpp"

12#include "../utility/math.hpp"

13#include "../utility/small_vector.hpp"

14#include "../utility/serializer.hpp"

15#include "../utility/lazy_string.hpp"

16#include "error.hpp"

17#include "declarations.hpp"

18#include "semaphore.hpp"

19#include "environment.hpp"

20#include "topology.hpp"

21#include "wsq.hpp"

22

23

28

29namespace tf {

30

31// ----------------------------------------------------------------------------

32// Class: Graph

33// ----------------------------------------------------------------------------

34

47class Graph {

48

49friend class Node;

50friend class FlowBuilder;

51friend class Subflow;

52friend class Taskflow;

53friend class Executor;

54

55public:

56

60Graph() = default;

61

65~Graph();

66

70Graph(const Graph&) = delete;

71

75Graph(Graph&&);

76

80Graph& operator =(const Graph&) = delete;

81

85Graph& operator =(Graph&&);

86

90void clear();

91

95size_t size() const;

96

100bool empty() const;

101

105auto begin();

106

110auto end();

111

115auto begin() const;

116

120auto end() const;

121

122private:

123

124 std::vector<Node*> _nodes;

125

126void _erase(Node*);

127

131template <typename ...ArgsT>

132 Node* _emplace_back(ArgsT&&...);

133};

134

135// ----------------------------------------------------------------------------

136// TaskParams

137// ----------------------------------------------------------------------------

138

161template <typename T>

162concept StringLike = std::convertible_to<T, std::string_view>;

163

171class TaskParams {

172

173public:

174

178 std::string name;

179

183void* data {nullptr};

184};

185

191class DefaultTaskParams {};

192

201template <typename P>

202concept TaskParamsLike =

203 std::same_as<std::decay_t<P>, TaskParams> ||

204 std::same_as<std::decay_t<P>, DefaultTaskParams> ||

205StringLike<P>;

206

214template <typename P>

215constexpr bool is_task_params_v = TaskParamsLike<P>;

216

217// ----------------------------------------------------------------------------

218// NodeBase

219// ----------------------------------------------------------------------------

220

224class NodeBase {

225

226friend class Node;

227friend class Graph;

228friend class Task;

229friend class AsyncTask;

230friend class TaskView;

231friend class Taskflow;

232friend class Executor;

233friend class FlowBuilder;

234friend class Subflow;

235friend class Runtime;

236friend class NonpreemptiveRuntime;

237friend class ExplicitAnchorGuard;

238friend class TaskGroup;

239friend class Algorithm;

240

241protected:

242

243 nstate_t _nstate {NSTATE::NONE};

244 std::atomic<estate_t> _estate {ESTATE::NONE};

245

246 NodeBase* _parent {nullptr};

247 std::atomic<size_t> _join_counter {0};

248

249 std::exception_ptr _exception_ptr {nullptr};

250

251 NodeBase() = default;

252

253 NodeBase(nstate_t nstate, estate_t estate, NodeBase* parent, size_t join_counter) :

254 _nstate {nstate},

255 _estate {estate},

256 _parent {parent},

257 _join_counter {join_counter} {

258 }

259

260void _rethrow_exception() {

261if(_exception_ptr) {

262auto e = _exception_ptr;

263 _exception_ptr = nullptr;

264 _estate.fetch_and(~(ESTATE::EXCEPTION | ESTATE::CAUGHT), std::memory_order_relaxed);

265 std::rethrow_exception(e);

266 }

267 }

268};

269

270// ----------------------------------------------------------------------------

271// Topology

272// ----------------------------------------------------------------------------

273

277class Topology : public NodeBase {

278

279friend class Executor;

280friend class Subflow;

281friend class Runtime;

282friend class NonpreemptiveRuntime;

283friend class Node;

284

285template <typename T>

286friend class Future;

287

288public:

289

290template <typename Predicate, typename OnFinish>

291 Topology(Taskflow&, Predicate&&, OnFinish&&);

292

293bool cancelled() const;

294

295private:

296

297 Taskflow& _taskflow;

298

299 std::promise<void> _promise;

300

301 std::function<bool()> _predicate;

302 std::function<void()> _on_finish;

303

304void _carry_out_promise();

305};

306

307// Constructor

308template <typename Predicate, typename OnFinish>

309Topology::Topology(Taskflow& tf, Predicate&& predicate, OnFinish&& on_finish):

310 NodeBase(NSTATE::NONE, ESTATE::EXPLICITLY_ANCHORED, nullptr, 0),

311 _taskflow(tf),

312 _predicate(std::forward<Predicate>(predicate)),

313 _on_finish(std::forward<OnFinish> (on_finish)) {

314}

315

316// Procedure

317inline void Topology::_carry_out_promise() {

318if(_exception_ptr) {

319auto e = _exception_ptr;

320 _exception_ptr = nullptr;

321 _promise.set_exception(e);

322 }

323else {

324 _promise.set_value();

325 }

326}

327

328// Function: cancelled

329inline bool Topology::cancelled() const {

330return _estate.load(std::memory_order_relaxed) & (ESTATE::CANCELLED | ESTATE::EXCEPTION);

331}

332

333

334// ----------------------------------------------------------------------------

335// Node

336// ----------------------------------------------------------------------------

337

341class Node : public NodeBase {

342

343friend class Graph;

344friend class Task;

345friend class AsyncTask;

346friend class TaskView;

347friend class Taskflow;

348friend class Executor;

349friend class FlowBuilder;

350friend class Subflow;

351friend class Runtime;

352friend class NonpreemptiveRuntime;

353friend class ExplicitAnchorGuard;

354friend class TaskGroup;

355friend class Algorithm;

356

357using Placeholder = std::monostate;

358

359// static work handle

360struct Static {

361

362template <typename C>

363 Static(C&&);

364

365 std::function<void()> work;

366 };

367

368// runtime work handle

369struct Runtime {

370

371template <typename C>

372 Runtime(C&&);

373

374 std::function<void(tf::Runtime&)> work;

375 };

376

377struct NonpreemptiveRuntime {

378

379template <typename C>

380 NonpreemptiveRuntime(C&&);

381

382 std::function<void(tf::NonpreemptiveRuntime&)> work;

383 };

384

385// subflow work handle

386struct Subflow {

387

388template <typename C>

389 Subflow(C&&);

390

391 std::function<void(tf::Subflow&)> work;

392 Graph subgraph;

393 };

394

395// condition work handle

396struct Condition {

397

398template <typename C>

399 Condition(C&&);

400

401 std::function<int()> work;

402 };

403

404// multi-condition work handle

405struct MultiCondition {

406

407template <typename C>

408 MultiCondition(C&&);

409

410 std::function<SmallVector<int>()> work;

411 };

412

413// module work handle

414struct Module {

415

416 Module(Graph&);

417

418 Graph& graph;

419 };

420

421// adopted module work handle

422struct AdoptedModule {

423

424 AdoptedModule(Graph&&);

425

426 Graph graph;

427 };

428

429// Async work

430struct Async {

431

432template <typename T>

433 Async(T&&);

434

435 std::variant<

436 std::function<void()>,

437 std::function<void(tf::Runtime&)>, // silent async

438 std::function<void(tf::Runtime&, bool)> // async

439 > work;

440 };

441

442// silent dependent async

443struct DependentAsync {

444

445template <typename C>

446 DependentAsync(C&&);

447

448 std::variant<

449 std::function<void()>,

450 std::function<void(tf::Runtime&)>, // silent async

451 std::function<void(tf::Runtime&, bool)> // async

452 > work;

453

454// use_count is packed into the lower 24 bits of NodeBase::_estate

455// (ESTATE::REFCOUNT_MASK) to avoid a separate atomic and a std::get_if

456// call on every AsyncTask copy/move/destroy. see ESTATE::REFCOUNT_ONE.

457 };

458

459using handle_t = std::variant<

460 Placeholder, // placeholder

461 Static, // static tasking

462 Runtime, // runtime tasking

463 NonpreemptiveRuntime, // runtime (non-preemptive) tasking

464 Subflow, // subflow tasking

465 Condition, // conditional tasking

466 MultiCondition, // multi-conditional tasking

467 Module, // composable tasking

468 AdoptedModule, // composable tasking with move semantics

469 Async, // async tasking

470 DependentAsync // dependent async tasking

471 >;

472

473struct Semaphores {

474 SmallVector<Semaphore*> to_acquire;

475 SmallVector<Semaphore*> to_release;

476 };

477

478public:

479

480// variant index

481constexpr static auto PLACEHOLDER = get_index_v<Placeholder, handle_t>;

482constexpr static auto STATIC = get_index_v<Static, handle_t>;

483constexpr static auto RUNTIME = get_index_v<Runtime, handle_t>;

484constexpr static auto NONPREEMPTIVE_RUNTIME = get_index_v<NonpreemptiveRuntime, handle_t>;

485constexpr static auto SUBFLOW = get_index_v<Subflow, handle_t>;

486constexpr static auto CONDITION = get_index_v<Condition, handle_t>;

487constexpr static auto MULTI_CONDITION = get_index_v<MultiCondition, handle_t>;

488constexpr static auto MODULE = get_index_v<Module, handle_t>;

489constexpr static auto ADOPTED_MODULE = get_index_v<AdoptedModule, handle_t>;

490constexpr static auto ASYNC = get_index_v<Async, handle_t>;

491constexpr static auto DEPENDENT_ASYNC = get_index_v<DependentAsync, handle_t>;

492

493 Node() = default;

494

495template <typename... Args>

496 Node(nstate_t, estate_t, const TaskParams&, Topology*, NodeBase*, size_t, Args&&...);

497

498template <typename... Args>

499 Node(nstate_t, estate_t, const DefaultTaskParams&, Topology*, NodeBase*, size_t, Args&&...);

500

501template <StringLike S, typename... Args>

502 Node(nstate_t, estate_t, S&&, Topology*, NodeBase*, size_t, Args&&...);

503

504size_t num_successors() const;

505size_t num_predecessors() const;

506size_t num_strong_dependencies() const;

507size_t num_weak_dependencies() const;

508

509const std::string& name() const;

510

511private:

512

513 std::string _name;

514

515void* _data {nullptr};

516

517 Topology* _topology {nullptr};

518

519size_t _num_successors {0};

520 SmallVector<Node*, 4> _edges;

521

522 handle_t _handle;

523

524 std::unique_ptr<Semaphores> _semaphores;

525

526bool _is_parent_cancelled() const;

527bool _is_conditioner() const;

528bool _acquire_all(SmallVector<Node*>&);

529void _release_all(SmallVector<Node*>&);

530void _precede(Node*);

531void _set_up_join_counter();

532

533void _remove_successors(Node*);

534void _remove_predecessors(Node*);

535};

536

537

538// ----------------------------------------------------------------------------

539// Definition for Node::Static

540// ----------------------------------------------------------------------------

541

542// Constructor

543template <typename C>

544Node::Static::Static(C&& c) : work {std::forward<C>(c)} {

545}

546

547// ----------------------------------------------------------------------------

548// Definition for Node::Runtime

549// ----------------------------------------------------------------------------

550

551// Constructor

552template <typename C>

553Node::Runtime::Runtime(C&& c) : work {std::forward<C>(c)} {

554}

555

556// Constructor

557template <typename C>

558Node::NonpreemptiveRuntime::NonpreemptiveRuntime(C&& c) : work {std::forward<C>(c)} {

559}

560

561// ----------------------------------------------------------------------------

562// Definition for Node::Subflow

563// ----------------------------------------------------------------------------

564

565// Constructor

566template <typename C>

567Node::Subflow::Subflow(C&& c) : work {std::forward<C>(c)} {

568}

569

570// ----------------------------------------------------------------------------

571// Definition for Node::Condition

572// ----------------------------------------------------------------------------

573

574// Constructor

575template <typename C>

576Node::Condition::Condition(C&& c) : work {std::forward<C>(c)} {

577}

578

579// ----------------------------------------------------------------------------

580// Definition for Node::MultiCondition

581// ----------------------------------------------------------------------------

582

583// Constructor

584template <typename C>

585Node::MultiCondition::MultiCondition(C&& c) : work {std::forward<C>(c)} {

586}

587

588// ----------------------------------------------------------------------------

589// Definition for Node::Module

590// ----------------------------------------------------------------------------

591

592// Constructor

593inline Node::Module::Module(Graph& g) : graph(g){

594}

595

596// Constructor

597inline Node::AdoptedModule::AdoptedModule(Graph&& g) : graph(std::move(g)){

598}

599

600// ----------------------------------------------------------------------------

601// Definition for Node::Async

602// ----------------------------------------------------------------------------

603

604// Constructor

605template <typename C>

606Node::Async::Async(C&& c) : work {std::forward<C>(c)} {

607}

608

609// ----------------------------------------------------------------------------

610// Definition for Node::DependentAsync

611// ----------------------------------------------------------------------------

612

613// Constructor

614template <typename C>

615Node::DependentAsync::DependentAsync(C&& c) : work {std::forward<C>(c)} {

616}

617

618// ----------------------------------------------------------------------------

619// Definition for Node

620// ----------------------------------------------------------------------------

621

622// Constructor

623template <typename... Args>

624Node::Node(

625 nstate_t nstate,

626 estate_t estate,

627const TaskParams& params,

628 Topology* topology,

629 NodeBase* parent,

630size_t join_counter,

631 Args&&... args

  1. :

633 NodeBase(nstate, estate, parent, join_counter),

634 _name {params.name},

635 _data {params.data},

636 _topology {topology},

637 _handle {std::forward<Args>(args)...} {

638}

639

640// Constructor

641template <typename... Args>

642Node::Node(

643 nstate_t nstate,

644 estate_t estate,

645const DefaultTaskParams&,

646 Topology* topology,

647 NodeBase* parent,

648size_t join_counter,

649 Args&&... args

  1. :

651 NodeBase(nstate, estate, parent, join_counter),

652 _topology {topology},

653 _handle {std::forward<Args>(args)...} {

654}

655

656// Constructor

657template <StringLike S, typename... Args>

658Node::Node(

659 nstate_t nstate,

660 estate_t estate,

661 S&& name,

662 Topology* topology,

663 NodeBase* parent,

664size_t join_counter,

665 Args&&... args

  1. :

667 NodeBase(nstate, estate, parent, join_counter),

668 _name {std::forward<S>(name)},

669 _topology {topology},

670 _handle {std::forward<Args>(args)...} {

671}

672

674//template <typename T, typename... Args>

675//void Node::reset(

676// nstate_t nstate,

677// estate_t estate,

678// const TaskParams& params,

679// Topology* topology,

680// NodeBase* parent,

681// size_t join_counter,

682// std::in_place_type_t<T>,

683// Args&&... args

684//) {

685// _nstate = nstate;

686// _estate = estate;

687// _parent = parent;

688// _join_counter.store(join_counter, std::memory_order_relaxed);

689// _exception_ptr = nullptr;

690// _name = params.name;

691// _data = params.data;

692// _topology = topology;

693// _handle.emplace<T>(std::forward<Args>(args)...);

694// _num_successors = 0;

695// _edges.clear();

696// _semaphores.reset();

697//}

698//

700//template <typename T, typename... Args>

701//void Node::reset(

702// nstate_t nstate,

703// estate_t estate,

704// const DefaultTaskParams&,

705// Topology* topology,

706// NodeBase* parent,

707// size_t join_counter,

708// std::in_place_type_t<T>,

709// Args&&... args

710//) {

711// _nstate = nstate;

712// _estate = estate;

713// _parent = parent;

714// _join_counter.store(join_counter, std::memory_order_relaxed);

715// _exception_ptr = nullptr;

716// _name.clear();

717// _data = nullptr;

718// _topology = topology;

719// _handle.emplace<T>(std::forward<Args>(args)...);

720// _num_successors = 0;

721// _edges.clear();

722// _semaphores.reset();

723//}

724

725// Procedure: _precede

726/*

727u edges layout: s1, s2, s3, p1, p2 (num_successors = 3)

728v edges layout: s1, p1, p2

729

730add a new successor: u->v

731u successor layout:

732 s1, s2, s3, p1, p2, v (push_back v)

733 s1, s2, s3, v, p2, p1 (swap edges[num_successors] with edges[n-1])

734v predecessor layout:

735 s1, p1, p2, u (push_back u)

736*/

737inline void Node::_precede(Node* v) {

738 _edges.push_back(v);

739 std::swap(_edges[_num_successors++], _edges[_edges.size() - 1]);

740 v->_edges.push_back(this);

741}

742

743// Function: _remove_successors

744inline void Node::_remove_successors(Node* node) {

745auto sit = std::remove(_edges.begin(), _edges.begin() + _num_successors, node);

746size_t new_num_successors = std::distance(_edges.begin(), sit);

747 std::move(_edges.begin() + _num_successors, _edges.end(), sit);

748 _edges.resize(_edges.size() - (_num_successors - new_num_successors));

749 _num_successors = new_num_successors;

750}

751

752// Function: _remove_predecessors

753inline void Node::_remove_predecessors(Node* node) {

754 _edges.erase(

755 std::remove(_edges.begin() + _num_successors, _edges.end(), node), _edges.end()

756 );

757}

758

759// Function: num_successors

760inline size_t Node::num_successors() const {

761return _num_successors;

762}

763

764// Function: predecessors

765inline size_t Node::num_predecessors() const {

766return _edges.size() - _num_successors;

767}

768

769// Function: num_weak_dependencies

770inline size_t Node::num_weak_dependencies() const {

771size_t n = 0;

772for(size_t i=_num_successors; i<_edges.size(); i++) {

773 n += _edges[i]->_is_conditioner();

774 }

775return n;

776}

777

778// Function: num_strong_dependencies

779inline size_t Node::num_strong_dependencies() const {

780size_t n = 0;

781for(size_t i=_num_successors; i<_edges.size(); i++) {

782 n += !_edges[i]->_is_conditioner();

783 }

784return n;

785}

786

787// Function: name

788inline const std::string& Node::name() const {

789return _name;

790}

791

792// Function: _is_conditioner

793inline bool Node::_is_conditioner() const {

794return _handle.index() == Node::CONDITION ||

795 _handle.index() == Node::MULTI_CONDITION;

796}

797

798// Function: _is_parent_cancelled

799inline bool Node::_is_parent_cancelled() const {

800return (_topology && (_topology->_estate.load(std::memory_order_relaxed) & (ESTATE::CANCELLED | ESTATE::EXCEPTION)))

801 ||

802 (_parent && (_parent->_estate.load(std::memory_order_relaxed) & (ESTATE::CANCELLED | ESTATE::EXCEPTION)));

803}

804

805// Procedure: _set_up_join_counter

806inline void Node::_set_up_join_counter() {

807//assert(_nstate == NSTATE::NONE);

808for(size_t i=_num_successors; i<_edges.size(); i++) {

809 _nstate += !_edges[i]->_is_conditioner();

810 }

811 _join_counter.store(_nstate & NSTATE::STRONG_DEPENDENCIES_MASK, std::memory_order_relaxed);

812}

813

814

815// Function: _acquire_all

816inline bool Node::_acquire_all(SmallVector<Node*>& nodes) {

817// assert(_semaphores != nullptr);

818auto& to_acquire = _semaphores->to_acquire;

819for(size_t i = 0; i < to_acquire.size(); ++i) {

820if(!to_acquire[i]->_try_acquire_or_wait(this)) {

821for(size_t j = 1; j <= i; ++j) {

822 to_acquire[i-j]->_release(nodes);

823 }

824return false;

825 }

826 }

827return true;

828}

829

830// Function: _release_all

831inline void Node::_release_all(SmallVector<Node*>& nodes) {

832// assert(_semaphores != nullptr);

833auto& to_release = _semaphores->to_release;

834for(const auto& sem : to_release) {

835 sem->_release(nodes);

836 }

837}

838

839

840

841// ----------------------------------------------------------------------------

842// ExplicitAnchorGuard

843// ----------------------------------------------------------------------------

844

848class ExplicitAnchorGuard {

849

850public:

851

852// Explicit anchor must sit in estate as it may be accessed by multiple threads

853// (e.g., corun's parent with tear_down_async's parent).

854 ExplicitAnchorGuard(NodeBase* node_base) : _node_base{node_base} {

855 _node_base->_estate.fetch_or(ESTATE::EXPLICITLY_ANCHORED, std::memory_order_relaxed);

856 }

857

858 ~ExplicitAnchorGuard() {

859 _node_base->_estate.fetch_and(~ESTATE::EXPLICITLY_ANCHORED, std::memory_order_relaxed);

860 }

861

862private:

863

864 NodeBase* _node_base;

865};

866

867// ----------------------------------------------------------------------------

868// Node Object Pool

869// ----------------------------------------------------------------------------

870

871#ifdef TF_ENABLE_TASK_POOL

875using NodePool = std::conditional_t

876 std::atomic<tf::TaggedHead128>::is_always_lock_free,

877 ObjectPool<Node, tf::TaggedHead128>,

878 ObjectPool<Node, tf::TaggedHead64<>>

879>;

880inline NodePool _node_pool;

881#endif

882

886template <typename... ArgsT>

887TF_FORCE_INLINE Node* animate(ArgsT&&... args) {

888#ifdef TF_ENABLE_TASK_POOL

889return _node_pool.animate(std::forward<ArgsT>(args)...);

890#else

891return new Node(std::forward<ArgsT>(args)...);

892#endif

893}

894

898TF_FORCE_INLINE void recycle(Node* ptr) {

899#ifdef TF_ENABLE_TASK_POOL

900 _node_pool.recycle(ptr);

901#else

902delete ptr;

903#endif

904}

905

906

907// ----------------------------------------------------------------------------

908// Graph definition

909// ----------------------------------------------------------------------------

910

911// Destructor

912inline Graph::~Graph() {

913clear();

914}

915

916// Move constructor

917inline Graph::Graph(Graph&& other) :

918 _nodes {std::move(other._nodes)} {

919}

920

921// Move assignment

922inline Graph& Graph::operator =(Graph&& other) {

923clear();

924 _nodes = std::move(other._nodes);

925return *this;

926}

927

928// Procedure: clear

929inline void Graph::clear() {

930for(auto node : _nodes) {

931 recycle(node);

932 }

933 _nodes.clear();

934}

935

936// Function: size

937inline size_t Graph::size() const {

938return _nodes.size();

939}

940

941// Function: empty

942inline bool Graph::empty() const {

943return _nodes.empty();

944}

945

946// Function: begin

947inline auto Graph::begin() {

948return _nodes.begin();

949}

950

951// Function: end

952inline auto Graph::end() {

953return _nodes.end();

954}

955

956// Function: begin

957inline auto Graph::begin() const {

958return _nodes.begin();

959}

960

961// Function: end

962inline auto Graph::end() const {

963return _nodes.end();

964}

965

966// Function: erase

967inline void Graph::_erase(Node* node) {

968//erase(

969// std::remove_if(begin(), end(), [&](auto& p){ return p.get() == node; }),

970// end()

971//);

972 _nodes.erase(

973 std::remove_if(_nodes.begin(), _nodes.end(), [&](auto& p){

974 if(p == node) {

975 recycle(p);

976 return true;

977 }

978return false;

979 }),

980 _nodes.end()

981 );

982}

983

987template <typename ...ArgsT>

988Node* Graph::_emplace_back(ArgsT&&... args) {

989 _nodes.push_back(animate(std::forward<ArgsT>(args)...));

990return _nodes.back();

991}

992

993// ----------------------------------------------------------------------------

994// Graph checker

995// ----------------------------------------------------------------------------

996

997

1027template <typename T>

1028concept GraphLike = std::derived_from<T, Graph> ||

1029requires(T& t) {

1030 { t.graph() } -> std::convertible_to<Graph&>;

1031 };

1032

1066template <GraphLike T>

1067Graph& retrieve_graph(T& target) {

1068if constexpr (requires { target.graph(); }) {

1069return target.graph();

1070 } else {

1071return static_cast<Graph&>(target);

1072 }

1073}

1074

1075} // end of namespace tf. ----------------------------------------------------

tf::AsyncTask

class to hold a dependent asynchronous task with shared ownership

Definition async_task.hpp:45

tf::DefaultTaskParams

class to create an empty task parameter for compile-time optimization

Definition graph.hpp:191

tf::Executor

class to create an executor

Definition executor.hpp:62

tf::FlowBuilder

class to build a task dependency graph

Definition flow_builder.hpp:22

tf::Graph

class to create a graph object

Definition graph.hpp:47

tf::Graph::operator=

Graph & operator=(const Graph &)=delete

disabled copy assignment operator

tf::Graph::Graph

Graph()=default

constructs the graph object

tf::Graph::empty

bool empty() const

queries the emptiness of the graph

Definition graph.hpp:942

tf::Graph::~Graph

~Graph()

destroys the graph object

Definition graph.hpp:912

tf::Graph::end

auto end()

returns an iterator past the last element of this graph

Definition graph.hpp:952

tf::Graph::size

size_t size() const

returns the number of nodes in the graph

Definition graph.hpp:937

tf::Graph::clear

void clear()

clears the graph

Definition graph.hpp:929

tf::Graph::begin

auto begin()

returns an iterator to the first node of this graph

Definition graph.hpp:947

tf::Graph::Graph

Graph(const Graph &)=delete

disabled copy constructor

tf::Runtime

class to create a runtime task

Definition runtime.hpp:47

tf::Subflow

class to construct a subflow graph from the execution of a dynamic task

Definition flow_builder.hpp:1735

tf::TaskGroup

class to create a task group from a task

Definition task_group.hpp:61

tf::TaskParams

class to create a task parameter object

Definition graph.hpp:171

tf::TaskParams::name

std::string name

name of the task

Definition graph.hpp:178

tf::TaskParams::data

void * data

C-styled pointer to user data.

Definition graph.hpp:183

tf::TaskView

class to access task information from the observer interface

Definition task.hpp:1546

tf::Task

class to create a task handle over a taskflow node

Definition task.hpp:569

tf::Taskflow

class to create a taskflow object

Definition taskflow.hpp:64

tf::GraphLike

concept that determines if a type owns or provides access to a tf::Graph

Definition graph.hpp:1028

tf::StringLike

concept that determines if a type is string-like

Definition graph.hpp:162

tf::TaskParamsLike

determines if a type is a task parameter type

Definition graph.hpp:202

tf

taskflow namespace

Definition small_vector.hpp:20

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::retrieve_graph

Graph & retrieve_graph(T &target)

retrieves a reference to the underlying tf::Graph from an object

Definition graph.hpp:1067

tf::is_task_params_v

constexpr bool is_task_params_v

determines if a type is a task parameter type (variable template)

Definition graph.hpp:215