+#if __TBB_FLOW_GRAPH_CPP11_FEATURES
+
+//composite_node
+template< typename InputTuple, typename OutputTuple > class composite_node;
+
+template< typename... InputTypes, typename... OutputTypes>
+class composite_node <tbb::flow::tuple<InputTypes...>, tbb::flow::tuple<OutputTypes...> > : public graph_node, tbb::internal::no_copy {
+
+public:
+ typedef tbb::flow::tuple< receiver<InputTypes>&... > input_ports_type;
+ typedef tbb::flow::tuple< sender<OutputTypes>&... > output_ports_type;
+
+private:
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+ const char *my_type_name;
+#endif
+ input_ports_type *my_input_ports;
+ output_ports_type *my_output_ports;
+
+ static const size_t NUM_INPUTS = sizeof...(InputTypes);
+ static const size_t NUM_OUTPUTS = sizeof...(OutputTypes);
+
+protected:
+ /*override*/void reset_node(reset_flags) {}
+
+public:
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+ composite_node( graph &g, const char *type_name = "composite_node") : graph_node(g), my_type_name(type_name), my_input_ports(NULL), my_output_ports(NULL) {
+ tbb::internal::itt_make_task_group( tbb::internal::ITT_DOMAIN_FLOW, this, tbb::internal::FLOW_NODE, &g, tbb::internal::FLOW_GRAPH, tbb::internal::FLOW_COMPOSITE_NODE );
+ tbb::internal::fgt_multiinput_multioutput_node_desc( this, my_type_name );
+ }
+#else
+ composite_node( graph &g) : graph_node(g), my_input_ports(NULL), my_output_ports(NULL) {}
+#endif
+
+ template<typename T1, typename T2>
+ void set_external_ports(T1&& input_ports_tuple, T2&& output_ports_tuple) {
+ __TBB_STATIC_ASSERT(NUM_INPUTS == tbb::flow::tuple_size<input_ports_type>::value, "number of arguments does not match number of input ports");
+ __TBB_STATIC_ASSERT(NUM_OUTPUTS == tbb::flow::tuple_size<output_ports_type>::value, "number of arguments does not match number of output ports");
+ my_input_ports = new input_ports_type(std::forward<T1>(input_ports_tuple));
+ my_output_ports = new output_ports_type(std::forward<T2>(output_ports_tuple));
+
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+ tbb::internal::fgt_internal_input_helper<T1, NUM_INPUTS>::register_port( this, input_ports_tuple);
+ tbb::internal::fgt_internal_output_helper<T2, NUM_OUTPUTS>::register_port( this, output_ports_tuple);
+#endif
+ }
+
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+ template< typename... NodeTypes >
+ void add_visible_nodes(const NodeTypes&... n) { internal::add_nodes_impl(this, true, n...); }
+
+ template< typename... NodeTypes >
+ void add_nodes(const NodeTypes&... n) { internal::add_nodes_impl(this, false, n...); }
+#else
+ template<typename... Nodes> void add_nodes(Nodes&...) { }
+ template<typename... Nodes> void add_visible_nodes(Nodes&...) { }
+#endif
+
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+ /* override */ void set_name( const char *name ) {
+ tbb::internal::fgt_multiinput_multioutput_node_desc( this, name );
+ }
+#endif
+
+ input_ports_type input_ports() {
+ __TBB_ASSERT(my_input_ports, "input ports not set, call set_external_ports to set input ports");
+ return *my_input_ports;
+ }
+
+ output_ports_type output_ports() {
+ __TBB_ASSERT(my_output_ports, "output ports not set, call set_external_ports to set output ports");
+ return *my_output_ports;
+ }
+
+ virtual ~composite_node() {
+ if(my_input_ports) delete my_input_ports;
+ if(my_output_ports) delete my_output_ports;
+ }
+
+#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
+ /*override*/void extract() {
+ __TBB_ASSERT(false, "Current composite_node implementation does not support extract");
+ }
+#endif
+}; // class composite_node
+
+//composite_node with only input ports
+template< typename... InputTypes>
+class composite_node <tbb::flow::tuple<InputTypes...>, tbb::flow::tuple<> > : public graph_node, tbb::internal::no_copy {
+public:
+ typedef tbb::flow::tuple< receiver<InputTypes>&... > input_ports_type;
+
+private:
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+ const char *my_type_name;
+#endif
+ input_ports_type *my_input_ports;
+ static const size_t NUM_INPUTS = sizeof...(InputTypes);
+
+protected:
+ /*override*/void reset_node(reset_flags) {}
+
+public:
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+ composite_node( graph &g, const char *type_name = "composite_node") : graph_node(g), my_type_name(type_name), my_input_ports(NULL) {
+ tbb::internal::itt_make_task_group( tbb::internal::ITT_DOMAIN_FLOW, this, tbb::internal::FLOW_NODE, &g, tbb::internal::FLOW_GRAPH, tbb::internal::FLOW_COMPOSITE_NODE );
+ tbb::internal::fgt_multiinput_multioutput_node_desc( this, my_type_name );
+ }
+#else
+ composite_node( graph &g) : graph_node(g), my_input_ports(NULL) {}
+#endif
+
+ template<typename T>
+ void set_external_ports(T&& input_ports_tuple) {
+ __TBB_STATIC_ASSERT(NUM_INPUTS == tbb::flow::tuple_size<input_ports_type>::value, "number of arguments does not match number of input ports");
+
+ my_input_ports = new input_ports_type(std::forward<T>(input_ports_tuple));
+
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+ tbb::internal::fgt_internal_input_helper<T, NUM_INPUTS>::register_port( this, std::forward<T>(input_ports_tuple));
+#endif
+ }
+
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+ template< typename... NodeTypes >
+ void add_visible_nodes(const NodeTypes&... n) { internal::add_nodes_impl(this, true, n...); }
+
+ template< typename... NodeTypes >
+ void add_nodes( const NodeTypes&... n) { internal::add_nodes_impl(this, false, n...); }
+#else
+ template<typename... Nodes> void add_nodes(Nodes&...) {}
+ template<typename... Nodes> void add_visible_nodes(Nodes&...) {}
+#endif
+
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+ /* override */ void set_name( const char *name ) {
+ tbb::internal::fgt_multiinput_multioutput_node_desc( this, name );
+ }
+#endif
+
+ input_ports_type input_ports() {
+ __TBB_ASSERT(my_input_ports, "input ports not set, call set_external_ports to set input ports");
+ return *my_input_ports;
+ }
+
+ virtual ~composite_node() {
+ if(my_input_ports) delete my_input_ports;
+ }
+
+#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
+ /*override*/void extract() {
+ __TBB_ASSERT(false, "Current composite_node implementation does not support extract");
+ }
+#endif
+
+}; // class composite_node
+
+//composite_nodes with only output_ports
+template<typename... OutputTypes>
+class composite_node <tbb::flow::tuple<>, tbb::flow::tuple<OutputTypes...> > : public graph_node, tbb::internal::no_copy {
+public:
+ typedef tbb::flow::tuple< sender<OutputTypes>&... > output_ports_type;
+
+private:
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+ const char *my_type_name;
+#endif
+ output_ports_type *my_output_ports;
+ static const size_t NUM_OUTPUTS = sizeof...(OutputTypes);
+
+protected:
+ /*override*/void reset_node(reset_flags) {}
+
+public:
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+ composite_node( graph &g, const char *type_name = "composite_node") : graph_node(g), my_type_name(type_name), my_output_ports(NULL) {
+ tbb::internal::itt_make_task_group( tbb::internal::ITT_DOMAIN_FLOW, this, tbb::internal::FLOW_NODE, &g, tbb::internal::FLOW_GRAPH, tbb::internal::FLOW_COMPOSITE_NODE );
+ tbb::internal::fgt_multiinput_multioutput_node_desc( this, my_type_name );
+ }
+#else
+ composite_node( graph &g) : graph_node(g), my_output_ports(NULL) {}
+#endif
+
+ template<typename T>
+ void set_external_ports(T&& output_ports_tuple) {
+ __TBB_STATIC_ASSERT(NUM_OUTPUTS == tbb::flow::tuple_size<output_ports_type>::value, "number of arguments does not match number of output ports");
+
+ my_output_ports = new output_ports_type(std::forward<T>(output_ports_tuple));
+
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+ tbb::internal::fgt_internal_output_helper<T, NUM_OUTPUTS>::register_port( this, std::forward<T>(output_ports_tuple));
+#endif
+ }
+
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+ template<typename... NodeTypes >
+ void add_visible_nodes(const NodeTypes&... n) { internal::add_nodes_impl(this, true, n...); }
+
+ template<typename... NodeTypes >
+ void add_nodes(const NodeTypes&... n) { internal::add_nodes_impl(this, false, n...); }
+#else
+ template<typename... Nodes> void add_nodes(Nodes&...) {}
+ template<typename... Nodes> void add_visible_nodes(Nodes&...) {}
+#endif
+
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+ /* override */ void set_name( const char *name ) {
+ tbb::internal::fgt_multiinput_multioutput_node_desc( this, name );
+ }
+#endif
+
+ output_ports_type output_ports() {
+ __TBB_ASSERT(my_output_ports, "output ports not set, call set_external_ports to set output ports");
+ return *my_output_ports;
+ }
+
+ virtual ~composite_node() {
+ if(my_output_ports) delete my_output_ports;
+ }
+
+#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
+ /*override*/void extract() {
+ __TBB_ASSERT(false, "Current composite_node implementation does not support extract");
+ }
+#endif
+
+}; // class composite_node
+
+#endif // __TBB_PREVIEW_COMPOSITE_NODE
+
+#if __TBB_PREVIEW_ASYNC_NODE
+namespace internal {
+//! Pure virtual template class that defines interface for async communication
+template < typename Output >
+class async_gateway {
+public:
+ typedef Output output_type;
+
+ //! Submit signal from Async Activity to FG
+ virtual bool async_try_put(const output_type &i ) = 0;
+
+ virtual void async_reserve() = 0;
+
+ virtual void async_commit() = 0;
+
+ virtual ~async_gateway() {}
+};
+}
+
+//! Implements a async node
+template < typename Input, typename Output, typename Allocator=cache_aligned_allocator<Input> >
+class async_node : public graph_node, public internal::async_input<Input, Allocator, internal::async_gateway<Output> >, public internal::function_output<Output>, public internal::async_gateway<Output> {
+protected:
+ using graph_node::my_graph;
+public:
+ typedef Input input_type;
+ typedef Output output_type;
+ typedef async_node< input_type, output_type, Allocator > my_class;
+ typedef sender< input_type > predecessor_type;
+ typedef receiver< output_type > successor_type;
+ typedef internal::async_gateway< output_type > async_gateway_type;
+ typedef internal::async_input<input_type, Allocator, async_gateway_type > async_input_type;
+ typedef internal::function_output<output_type> async_output_type;
+