Intel® oneAPI Threading Building Blocks Developer Guide and API Reference
write_once_node
[flow_graph.write_once_node]
A node that is a buffer of a single item that cannot be overwritten.
// Defined in header <oneapi/tbb/flow_graph.h>
namespace oneapi {
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();
// Preview feature: Helper Functions for Expressing Graphs
explicit write_once_node(decltype(follows(...)));
explicit write_once_node(decltype(precedes(...)));
bool try_put( const T &v );
bool try_get( T &v );
// Preview feature: Waiting for Single Message
bool try_put_and_wait( const T &v );
bool is_valid( );
void clear( );
};
} // namespace flow
} // namespace tbb
} // namespace oneapi
Requirements:
The T type must meet the DefaultConstructible requirements from [defaultconstructible] and CopyAssignable requirements from [copyassignable] ISO C++ Standard sections.
This type of node buffers a single item of type T. The value is initially invalid. Gets from the node are non-destructive.
write_once_node is a graph_node, receiver<T> and sender<T>.
write_once_node has a buffering and broadcast-pushproperties.
write_once_node does not allow overwriting its single item buffer.
Member functions
explicitwrite_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(constwrite_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.
booltry_put(constT&v)
Stores v in the internal single item buffer if it does not contain a valid value already. If a new value is set, the node broadcast it to all successors.
Returns: true for the first time after construction or a call to clear(); false, otherwise.
booltry_get(T&v)
If the internal buffer is valid, assigns the value to v.
Returns: true if v is assigned to; false, otherwise.
boolis_valid()
Returns: true if the buffer holds a valid value; false, otherwise.
voidclear()
Invalidates the value held in the buffer.
Preview Features
The following preview features extend the write_once_node API:
Helper Functions for Expressing Graphs - allows write_once_node to be constructed as a successor or a predecessor of the set of nodes.
Waiting for Single Message in Flow Graph - allows to put messages to write_once_node and wait for all related work to complete.
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 "oneapi/tbb/flow_graph.h"
#include <tuple>
typedef int data_type;
int main() {
using namespace oneapi::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<std::tuple<data_type, data_type>, reserving> join_n(g);
function_node<std::tuple<data_type, data_type>> consumer_n(
g, unlimited,
[&](const std::tuple<data_type, data_type>& arg) {
// use the precomputed static result along with dynamic data
data_type precomputed_result = std::get<0>(arg);
data_type dynamic_data = std::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;
}