# 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();

            bool try_put( const T &v );
            bool try_get( 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-push properties.

`write_once_node` does not allow overwriting its single item buffer.

## Member functions

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 T &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.

bool try_get(T &v)

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

  Returns: `true` if `v` is assigned to; `false`, otherwise.

bool is_valid()

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

void clear()

  Invalidates the value held in the buffer.

## 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"

    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<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;
    }