Peano
Loading...
Searching...
No Matches
tbb::dynamic_task_graph_spawned_node Class Reference

Spawned node. More...

#include <dynamic_task_graph_spawned_node.h>

Collaboration diagram for tbb::dynamic_task_graph_spawned_node:

Public Types

enum class  State { Submitted , Spawned , Complete }
 

Public Member Functions

 dynamic_task_graph_spawned_node (const dynamic_task_graph_node &task_specification, dynamic_task_graph &task_graph)
 Create a new task node in the graph.
 
 dynamic_task_graph_spawned_node (const dynamic_task_graph_spawned_node &)=delete
 You cannot copy a spawned node.
 
void incoming_task_has_terminated ()
 Decrement the incoming task counter and run if now ready.
 
void add_incoming_task_dependency ()
 
void run ()
 Run the task.
 
std::string to_string () const
 Helper routine, which likely will not be there in TBB counterpart.
 
bool add_successor (std::shared_ptr< dynamic_task_graph_spawned_node > successor)
 
bool has_terminated () const
 

Private Attributes

State _state
 
std::function< void()> _functor
 
tbb::spin_mutex _dependencies_semaphore
 Semaphore over all the dependencies.
 
dynamic_task_graph_task_graph
 
int _number_of_in_dependencies
 
std::vector< std::shared_ptr< dynamic_task_graph_spawned_node > > _out_dependency
 

Detailed Description

Spawned node.

This class is only used internally within the task graph lib and not to be used directly by users. Users create instances of dynamic_task_graph_node. Once they put this node into a task_graph instance, it is tied to a new instance of spawned_task_graph_node.

Memory/heap management

As long as a task graph is alive, users might use it to introduce new task dependencies. So we have to ensure that the memory location is absolutely unique. Notably, we may not encounter a situation where a user submits a task A, this task is processed immediately, then creates a task B and a task C which depends on A (but not B). So B may never ever end up at the same memory location as A.

To avoid this, we work exclusively with smart pointers referencing spawned nodes.

Definition at line 46 of file dynamic_task_graph_spawned_node.h.

Member Enumeration Documentation

◆ State

Enumerator
Submitted 

Task is submitted but not yet running.

Initial state.

Spawned 

Task is now running.

The function tbb::dynamic_task_graph_spawned_node::run() toggles a task from Submitted into Spawned just before it hands the task over to the underlying task arena.

Complete 

Once a task has terminated, it toggles to complete.

This allows a wait, for example, to continue. However, it does not mean yet that we have also notified successors.

Definition at line 48 of file dynamic_task_graph_spawned_node.h.

Constructor & Destructor Documentation

◆ dynamic_task_graph_spawned_node() [1/2]

tbb::dynamic_task_graph_spawned_node::dynamic_task_graph_spawned_node ( const dynamic_task_graph_node & task_specification,
dynamic_task_graph & task_graph )

Create a new task node in the graph.

Creating a new task node means that we have to "invert" the edges in the underlying graph: An instance of task_specification knows which task are incoming. For the actual task graph, we need the outgoing tasks.

The default spawned task has one incoming dependency, i.e. is not ready. You have to manually decrease the counter after construction once all dependencies are in place.

Definition at line 11 of file dynamic_task_graph_spawned_node.cpp.

References __TBB_TRACE_TASK_CREATE.

◆ dynamic_task_graph_spawned_node() [2/2]

tbb::dynamic_task_graph_spawned_node::dynamic_task_graph_spawned_node ( const dynamic_task_graph_spawned_node & )
delete

You cannot copy a spawned node.

Member Function Documentation

◆ add_incoming_task_dependency()

void tbb::dynamic_task_graph_spawned_node::add_incoming_task_dependency ( )

Definition at line 27 of file dynamic_task_graph_spawned_node.cpp.

Referenced by tbb::dynamic_task_graph::put().

Here is the caller graph for this function:

◆ add_successor()

bool tbb::dynamic_task_graph_spawned_node::add_successor ( std::shared_ptr< dynamic_task_graph_spawned_node > successor)
Returns
has successfully added this node. If it returns false, then the task represented by this object has already terminated and we hence could not add anything anymore.

Definition at line 76 of file dynamic_task_graph_spawned_node.cpp.

References _state.

◆ has_terminated()

bool tbb::dynamic_task_graph_spawned_node::has_terminated ( ) const

Definition at line 71 of file dynamic_task_graph_spawned_node.cpp.

References _state.

Referenced by tbb::dynamic_task_graph::wait().

Here is the caller graph for this function:

◆ incoming_task_has_terminated()

void tbb::dynamic_task_graph_spawned_node::incoming_task_has_terminated ( )

Decrement the incoming task counter and run if now ready.

We first decrement the incoming task counter. This part has to be protected with a semaphore, so no two threads can decrement the task at the same time. While we decrement the task, we can check if it is ready.

If a task is ready, we can actually run() it.

Definition at line 33 of file dynamic_task_graph_spawned_node.cpp.

Referenced by tbb::dynamic_task_graph::put().

Here is the caller graph for this function:

◆ run()

void tbb::dynamic_task_graph_spawned_node::run ( )

Run the task.

This is the actual routine which hands the task over to TBB's runtime. The system is allowed to invoke it if and only if the task is ready, i.e. has no pending incoming dependencies anymore.

Algorithm steps

  1. Invoke the functor, i.e. do the actual task calculations. Note that other tasks still might add further outgoing dependencies at this point.
  2. Create our own smart pointer to the underlying instance of dynamic_tsak_graph_spawned_node. We will remove it from the list of spawned tasks next, which means it could be destroyed at this point. We still have to tidy it up however, so better to hold our own smart pointer.
  1. Remove the task from the set of spawned tasks. Noone should use this task after that anymore.
  2. Lock the task, as we now will change things. In theory, this should not be necessary, but someone might still hold a pointer to this task and try to alter it while we sort out the outgoing dependencies and ramp up the task.
  3. Inform all outgoing tasks that we are done.

Implementation

We work with catch by reference here, as we know that all the task's fields are still alive while we execute the task.

Todo
Write something about lazy deletion

Definition at line 46 of file dynamic_task_graph_spawned_node.cpp.

References __TBB_TRACE_TASK_COMPLETE, __TBB_TRACE_TASK_RUN, and _state.

◆ to_string()

std::string tbb::dynamic_task_graph_spawned_node::to_string ( ) const

Helper routine, which likely will not be there in TBB counterpart.

Definition at line 89 of file dynamic_task_graph_spawned_node.cpp.

References _state.

Field Documentation

◆ _dependencies_semaphore

tbb::spin_mutex tbb::dynamic_task_graph_spawned_node::_dependencies_semaphore
private

Semaphore over all the dependencies.

These are held in a container and hence need a proper mutex. All other states are realised as atomics to minimise locking.

Definition at line 165 of file dynamic_task_graph_spawned_node.h.

◆ _functor

std::function<void()> tbb::dynamic_task_graph_spawned_node::_functor
private

◆ _number_of_in_dependencies

int tbb::dynamic_task_graph_spawned_node::_number_of_in_dependencies
private

Definition at line 167 of file dynamic_task_graph_spawned_node.h.

◆ _out_dependency

std::vector< std::shared_ptr<dynamic_task_graph_spawned_node> > tbb::dynamic_task_graph_spawned_node::_out_dependency
private

Definition at line 168 of file dynamic_task_graph_spawned_node.h.

◆ _state

State tbb::dynamic_task_graph_spawned_node::_state
private

Definition at line 157 of file dynamic_task_graph_spawned_node.h.

◆ _task_graph

dynamic_task_graph& tbb::dynamic_task_graph_spawned_node::_task_graph
private

Definition at line 166 of file dynamic_task_graph_spawned_node.h.


The documentation for this class was generated from the following files: