# function_node Template Class

## Summary

A template class that is a graph_node, receiver<Input> and a sender<Output>. This node may have concurrency limits as set by the user. By default, a function_node has an internal FIFO buffer at its input. Messages that cannot be immediately processed due to concurrency limits are temporarily stored in this FIFO buffer. A template argument can be used to disable this internal buffer. If the FIFO buffer is disabled, incoming messages will be rejected if they cannot be processed immediately while respecting the concurrency limits of the node.

## Syntax

    template < typename Input,
               typename Output = continue_msg,
               graph_buffer_policy = queueing,
               typename A = cache_aligned_allocator<Input> >
    class function_node;

## Header

    #include "tbb/flow_graph.h"

## Description

A function_node receives messages of type Input at a single input port and generates a single output message of type Output that is broadcast to all successors. Rejection of messages by successors is handled using the protocol in Message Passing Protocol, see link below.

If graph_buffer_policy == queueing, an internal unbounded input buffer is maintained using memory obtained through an allocator of type A.

A function_node maintains an internal constant threshold T and an internal counter C. At construction, C = 0 and T is set the value passed in to the constructor. The behavior of a call to try_put is determined by the value of T and C as shown below.

Behavior of a call to a function_node's try_put
Value of threshold T | Value of counter C | bool try_put( const input_type &v )
--- | --- | ---
    T == flow::unlimited
| NA | A task is enqueued that broadcasts the result of body(v) to all successors. Returns true.
    T != flow::unlimited
| C < T | Increments C. A task is enqueued that broadcasts the result of body(v) to all successors and then decrements C. Returns true.
    T != flow::unlimited
| C >= T | If the template argument graph_buffer_policy==queueing, v is stored in an internal FIFO buffer until C < T. When T becomes less than C, C is incremented and a task is enqueued that broadcasts the result of body(v) to all successors and then decrements C. Returns true. If the template argument graph_buffer_policy==rejecting and C >= T, returns false.

A function_node has a user-settable concurrency limit. It can have flow::unlimited concurrency, which allows an unlimited number of invocations of the body to execute concurrently. It can have flow::serial concurrency, which allows only a single call of body to execute concurrently. The user can also provide a value of type size_t to limit concurrency to a value between 1 and unlimited.

A function_node with graph_buffer_policy==rejecting will maintain a predecessor set as described in the Message Passing Protocol, see link below. If the function_node transitions from a state where C >= T to a state where C < T, it will try to get new messages from its set of predecessors until C >= T or there are no valid predecessors left in the set.

### Note

A function_node can serve as a terminal node in the graph. The convention is to use an Output of continue_msg and attach no successor.

The Body concept for function_node is shown in below.

function_node<Input, Output> Body Concept
Pseudo-Signature | Semantics
--- | ---
    B::B( const B& )
| Copy constructor.
    B::~B()
| Destructor.
    void operator=( const B& )
| Assignment. The return type `void` in the pseudo-signature denotes that `operator=` is not required to return a value. The actual `operator=` can return a value, which will be ignored.
    Output B::operator() (const Input &v) const
| Perform operation on v and return value of type Output.

### Caution

The body object passed to a function_node is copied. Therefore updates to member variables will not affect the original object used to construct the node. If the state held within a body object must be inspected from outside of the node, the copy_body function can be used to obtain an updated copy.

### Caution

Input and Output must be copy-constructible and assignable.

### Note

The body object may throw or cancel its enclosing graph. See task_group_context and Exceptions sections for a description.

## Members

    namespace tbb {
    namespace flow {

    enum graph_buffer_policy {
       rejecting, reserving, queueing, tag_matching };

    template < typename Input, typename Output = continue_msg,
               graph_buffer_policy = queueing,
               typename A = cache_aligned_allocator<Input> >
    class function_node :
      public graph_node, public receiver<Input>,
      public sender<Output> {
    public:
        template<typename Body>
        function_node( graph &g, size_t concurrency, Body body );
        function_node( const function_node &src );

        // receiver<Input>
        typedef Input 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<Output>
        typedef Output 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( );
    };

    }
    }

The following table provides additional information on the members of this template class.
Member | Description
--- | ---
template< typename Body> function_node(graph &g, size_t concurrency, Body body) | Constructs a function_node that will invoke a copy of body. At most concurrency calls to body may be made concurrently.
function_node( const function_node &src ) | Constructs a function_node that has the same initial state that src had when it was constructed. The function_node that is constructed will have a reference to the same graph object as src, will have a copy of the initial body used by src, and have the same concurrency threshold as src. The predecessors and successors of src will not be copied. ### Caution The new body object is copy constructed from a copy of the original body provided to src at its construction. Therefore changes made to member variables in src's body after the construction of src will not affect the body of the new function_node.
bool try_put( const input_type &v ) | See the table above, "Behavior of a call to a `function_node`'s `try_put`," for more information. Returns: true if the input was accepted; and false otherwise.
bool register_predecessor( predecessor_type &p ) | Adds p to the set of predecessors. Returns: true
bool remove_predecessor( predecessor_type &p ) | Removes p from the set of predecessors. Returns: true
bool register_successor( successor_type &r ) | Adds r to the set of successors. Returns: true
bool remove_successor( successor_type &r ) | Removes r from the set of successors. Returns: true
bool try_get( output_type &v ) | A function_node does not contain buffering of its output. Therefore it always rejects try_get calls. Returns: false
bool try_reserve( output_type &v ) | A function_node does not contain buffering of its output. Therefore it cannot be reserved. Returns: false
bool try_release( ) | A function_node does not contain buffering of its output. Therefore it cannot be reserved. Returns: false
bool try_consume( ) | A function_node does not contain buffering of its output. Therefore it cannot be reserved. Returns: false

Parent topic: Flow Graph

## See Also

copy_body Template Function
task_group_context
Exceptions
Message Passing Protocol