Summary

A template class that is a graph_node, receiver<Input> and sender<Output>. A write_once_node is a buffer of a single item that cannot be over-written.

Syntax

template < typename T >
class write_once_node;

Header

#include "tbb/flow_graph.h"

Description

This type of node buffers a single item of type T. The value is initially invalid. The first try_put to the node will set the value of the internal buffer, and broadcast the new value to all successors. Subsequent puts are ignored, with received values being lost. The internal buffer may be cleared explicitly, after which a new value may be set. Gets from the node are non-destructive. If the internal value is valid, a try_get will return true and copy the buffer value to the output. If the internal value is invalid, try_get will return false.

Rejection of messages by successors is handled using the protocol described in the Message Passing Protocol.

T must be copy-constructible and assignable.

Example

Usage scenario is similar to overwrite_node but an internal buffer can be updated only after clear() call. The following example shows the possibility to connect the node to a reserving join_node, avoiding direct calls to the try_get() method from the body of the successor node.

#include "tbb/flow_graph.h"

typedef int data_type;

int main() {
    using namespace tbb::flow;

    graph g;

    function_node<data_type, data_type> static_result_computer_n(
        g, serial,
        [&](const data_type& msg) {
            // compute the result using incoming message and pass it further, e.g.:
            data_type result = data_type((msg << 2 + 3) / 4);
            return result;
        });
    write_once_node<data_type> write_once_n(g); // for buffering once computed value

    buffer_node<data_type> buffer_n(g);
    join_node<tuple<data_type, data_type>, reserving> join_n(g);

    function_node<tuple<data_type, data_type>> consumer_n(
        g, unlimited,
        [&](const tuple<data_type, data_type>& arg) {
            // use the precomputed static result along with dynamic data
            data_type precomputed_result = get<0>(arg);
            data_type dynamic_data = get<1>(arg);
        });

    make_edge(static_result_computer_n, write_once_n);
    make_edge(write_once_n, input_port<0>(join_n));
    make_edge(buffer_n, input_port<1>(join_n));
    make_edge(join_n, consumer_n);

    // do one-time calculation that will be reused many times further in the graph
    static_result_computer_n.try_put(1);

    for (int i = 0; i < 100; i++) {
        buffer_n.try_put(1);
    }

    g.wait_for_all();

    return 0;
}

Members

namespace tbb {
namespace flow {

template< typename T >
class write_once_node :
  public graph_node, public receiver<T>, public sender<T> {
public:
    explicit write_once_node( graph &g );
    write_once_node( const write_once_node &src );
    ~write_once_node();

    // receiver<T>
    typedef T input_type;
    typedef sender<input_type> predecessor_type;
    bool try_put( const input_type &v );
    bool register_predecessor( predecessor_type &p );
    bool remove_predecessor( predecessor_type &p );

    // sender<T>
    typedef T output_type;
    typedef receiver<output_type> successor_type;
    bool register_successor( successor_type &r );
    bool remove_successor( successor_type &r );
    bool try_get( output_type &v );
    bool try_reserve( output_type &v );
    bool try_release( );
    bool try_consume( );

    bool is_valid( );
    void clear( );
};

}
}
The following table provides additional information on the members of this template class.
Member Description
explicit write_once_node( graph &g )

Constructs an object of type write_once_node that belongs to the graph g, with an invalid internal buffer item.

write_once_node( const write_once_node &src )

Constructs an object of type write_once_node with an invalid internal buffer item. The buffered value and list of successors is NOT copied from src.

~write_once_node( )

Destroys the write_once_node.

bool try_put( const input_type &v )

Stores v in the internal single item buffer if it does not already contain a valid value. If a new value is set, it calls try_put(v) on all successors.

Returns: true for the first time after construction or a call to clear(), false otherwise.

bool register_predecessor( predecessor_type &p )

Never rejects puts and therefore does not need to maintain a list of predecessors.

Returns: false

bool remove_predecessor( predecessor_type &p )

Never rejects puts and therefore does not need to maintain a list of predecessors.

Returns: false

bool register_successor( successor_type &r )

Adds r to the set of successors. If a valid item v is held in the buffer, a task is spawned to call r.try_put(v).

Returns: true

bool remove_successor( successor_type &r )

Removes r from the set of successors.

Returns: true

bool try_get( output_type &v )

If the internal buffer is valid, assigns the value to v.

Returns: true if v is assigned to. false if v is not assigned to.

bool try_reserve( output_type &v )

If the internal buffer is valid, assigns the value to v.

Returns: true if v is assigned to. false if v is not assigned to.

bool try_release( )

Returns: true

bool try_consume( )

Returns: true

bool is_valid( )

Returns: true if the buffer holds a valid value, otherwise returns false.

void clear( )

Invalidates the value held in the buffer.

有关编译器优化的更完整信息,请参阅优化通知