Using source_node

An active source_node starts sending messages as soon as an edge is connected to it. If not properly managed, this can lead to dropped messages. By default, a source_node is active unless constructed in the inactive state:

template< typename Body > source_node( graph &g, Body body, bool is_active=true )

To activate an inactive source_node, you call the node's function activate:

    source_node< int > src( g, src_body(10), false );
    // use it in calls to make_edge…

To manage this, either all source_nodes should be constructed in the inactive state and then only activated after the entire flow graph is constructed, or else care must be taken to build the graph so that no messages are dropped.

For example, you can use the code in Data Flow Graph. In that implementation, the source_node is constructed in the inactive state and activated after all other edges are made:

      make_edge( squarer, summer );
      make_edge( cuber, summer );
      source_node< int > src( g, src_body(10), false );
      make_edge( src, squarer );
      make_edge( src, cuber );

In this example, if the source_node were constructed in the active state, it might send a message to squarer immediately after the edge to squarer is connected. Later, when the edge to cuber is connected, cuber will receive all future messages, but may have already missed some.

In general it is safest to create your source_nodes in the inactive state and then activate them after the whole graph is constructed. However, this approach serializes graph construction and graph execution.

Some graphs can be constructed safely with source_nodes active, allowing the overlap of construction and execution. If your graph is a directed acyclic graph (DAG), and each source_node has only one successor, you can construct your source_nodes in the active state if you construct the edges in reverse topological order; that is, make the edges at the largest depth in the tree first, and work back to the shallowest edges. For example, if src is a source_node and func1 and func2 are both function nodes, the following graph would not drop messages, even though src is constructed in the active state:

    const int limit = 10;
    int count = 0;
    graph g;
    source_node<int> src( g, [&]( int &v ) -> bool {
      if ( count < limit ) {
        v = count;
        return true;
      } else {
        return false;
    } );
    function_node<int,int> func1( g, 1, []( int i ) -> int {
      cout << i << "\n";
      return i;
    } );
    function_node<int,int> func2( g, 1, []( int i ) -> int {
      cout << i << "\n";
      return i;
    } );

    make_edge( func1, func2 );
    make_edge( src, func1 );


The above code is safe because the edge from func1 to func2 is made before the edge from src to func1. If the edge from src to func1 were made first, func1 might generate a message before func2 is attached to it; that message would be dropped. Also, src has only a single successor. If src had more than one successor, the successor that is attached first might receive messages that do not reach the successors that are attached after it.

For more complete information about compiler optimizations, see our Optimization Notice.