17 #ifndef __TBB_flow_graph_H
18 #define __TBB_flow_graph_H
20 #define __TBB_flow_graph_H_include_area
38 #if TBB_USE_THREADING_TOOLS && TBB_PREVIEW_FLOW_GRAPH_TRACE && ( __linux__ || __APPLE__ )
41 #pragma warning (push)
42 #pragma warning( disable: 2196 )
44 #define __TBB_NOINLINE_SYM __attribute__((noinline))
46 #define __TBB_NOINLINE_SYM
49 #if __TBB_PREVIEW_ASYNC_MSG
54 #if __TBB_PREVIEW_STREAMING_NODE
57 #include <unordered_map>
58 #include <type_traits>
59 #endif // __TBB_PREVIEW_STREAMING_NODE
61 #if TBB_DEPRECATED_FLOW_ENQUEUE
62 #define FLOW_SPAWN(a) tbb::task::enqueue((a))
64 #define FLOW_SPAWN(a) tbb::task::spawn((a))
67 #if TBB_DEPRECATED_FLOW_NODE_ALLOCATOR
68 #define __TBB_DEFAULT_NODE_ALLOCATOR(T) cache_aligned_allocator<T>
70 #define __TBB_DEFAULT_NODE_ALLOCATOR(T) null_type
74 #if __TBB_CPP11_TUPLE_PRESENT
79 using std::tuple_size;
80 using std::tuple_element;
85 #include "compat/tuple"
107 namespace interface11 {
132 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
137 template<
typename Order,
typename... Args>
struct node_set;
140 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
144 class edge_container {
147 typedef std::list<C *, tbb::tbb_allocator<C *> > edge_list_type;
149 void add_edge(C &
s) {
150 built_edges.push_back(&
s);
153 void delete_edge(C &
s) {
154 for (
typename edge_list_type::iterator i = built_edges.begin(); i != built_edges.end(); ++i) {
156 (
void)built_edges.erase(i);
162 void copy_edges(edge_list_type &v) {
166 size_t edge_count() {
167 return (
size_t)(built_edges.size());
176 template<
typename S >
void sender_extract(
S &
s);
177 template<
typename R >
void receiver_extract(R &r);
180 edge_list_type built_edges;
195 namespace interface11 {
200 if (right == NULL)
return left;
202 if (left == NULL)
return right;
213 #if __TBB_PREVIEW_ASYNC_MSG
219 template <
typename T >
class async_storage;
221 template<
typename T,
typename =
void >
222 struct async_helpers {
224 typedef T filtered_type;
226 static const bool is_async_type =
false;
228 static const void* to_void_ptr(
const T& t) {
229 return static_cast<const void*
>(&t);
232 static void* to_void_ptr(T& t) {
233 return static_cast<void*
>(&t);
236 static const T& from_void_ptr(
const void*
p) {
237 return *
static_cast<const T*
>(
p);
240 static T& from_void_ptr(
void*
p) {
241 return *
static_cast<T*
>(
p);
244 static task* try_put_task_wrapper_impl(receiver<T>*
const this_recv,
const void *
p,
bool is_async) {
249 task*
const new_task = msg.
my_storage->subscribe(*this_recv, this_recv->graph_reference());
257 return this_recv->try_put_task(from_void_ptr(
p));
262 template<
typename T >
263 struct async_helpers< T, typename std::enable_if< std::is_base_of<async_msg<typename T::async_msg_data_type>, T>::value >
::type > {
264 typedef T async_type;
265 typedef typename T::async_msg_data_type filtered_type;
267 static const bool is_async_type =
true;
270 static const void* to_void_ptr(
const T& t) {
274 static void* to_void_ptr(T& t) {
279 static const T& from_void_ptr(
const void*
p) {
283 static T& from_void_ptr(
void*
p) {
288 static task* try_put_task_wrapper_impl(receiver<T>*
const this_recv,
const void *
p,
bool is_async) {
291 return this_recv->try_put_task(from_void_ptr(
p));
296 const filtered_type& t = async_helpers<filtered_type>::from_void_ptr(
p);
298 return this_recv->try_put_task(msg);
303 class untyped_receiver;
305 class untyped_sender {
312 virtual ~untyped_sender() {}
330 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
331 typedef internal::edge_container<successor_type> built_successors_type;
333 typedef built_successors_type::edge_list_type successor_list_type;
334 virtual built_successors_type &built_successors() = 0;
335 virtual void internal_add_built_successor(
successor_type & ) = 0;
336 virtual void internal_delete_built_successor(
successor_type & ) = 0;
337 virtual void copy_successors( successor_list_type &) = 0;
338 virtual size_t successor_count() = 0;
342 template<
typename X >
343 bool try_get( X &t ) {
344 return try_get_wrapper( internal::async_helpers<X>::to_void_ptr(t), internal::async_helpers<X>::is_async_type );
348 template<
typename X >
350 return try_reserve_wrapper( internal::async_helpers<X>::to_void_ptr(t), internal::async_helpers<X>::is_async_type );
353 virtual bool try_get_wrapper(
void*
p,
bool is_async ) = 0;
354 virtual bool try_reserve_wrapper(
void*
p,
bool is_async ) = 0;
357 class untyped_receiver {
358 template<
typename,
typename >
friend class run_and_put_task;
364 #if __TBB_PREVIEW_OPENCL_NODE
365 template<
typename,
typename >
friend class proxy_dependency_receiver;
369 typedef untyped_sender predecessor_type;
372 virtual ~untyped_receiver() {}
376 bool try_put(
const X& t) {
377 task *res = try_put_task(t);
378 if (!res)
return false;
388 virtual bool register_predecessor( predecessor_type & ) {
return false; }
391 virtual bool remove_predecessor( predecessor_type & ) {
return false; }
393 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
394 typedef internal::edge_container<predecessor_type> built_predecessors_type;
395 typedef built_predecessors_type::edge_list_type predecessor_list_type;
396 virtual built_predecessors_type &built_predecessors() = 0;
397 virtual void internal_add_built_predecessor( predecessor_type & ) = 0;
398 virtual void internal_delete_built_predecessor( predecessor_type & ) = 0;
399 virtual void copy_predecessors( predecessor_list_type & ) = 0;
400 virtual size_t predecessor_count() = 0;
404 task *try_put_task(
const X& t) {
405 return try_put_task_wrapper( internal::async_helpers<X>::to_void_ptr(t), internal::async_helpers<X>::is_async_type );
408 virtual task* try_put_task_wrapper(
const void*
p,
bool is_async ) = 0;
410 virtual graph& graph_reference()
const = 0;
417 virtual bool is_continue_receiver() {
return false; }
423 template<
typename T >
424 class sender :
public internal::untyped_sender {
429 __TBB_DEPRECATED typedef typename internal::async_helpers<T>::filtered_type filtered_type;
432 virtual bool try_get( T & ) {
return false; }
438 virtual bool try_get_wrapper(
void*
p,
bool is_async )
__TBB_override {
440 if ( internal::async_helpers<T>::is_async_type == is_async ) {
441 return try_get( internal::async_helpers<T>::from_void_ptr(
p) );
444 __TBB_ASSERT(
false,
"async_msg interface does not support 'pull' protocol in try_get()");
448 virtual bool try_reserve_wrapper(
void*
p,
bool is_async )
__TBB_override {
450 if ( internal::async_helpers<T>::is_async_type == is_async ) {
451 return try_reserve( internal::async_helpers<T>::from_void_ptr(
p) );
454 __TBB_ASSERT(
false,
"async_msg interface does not support 'pull' protocol in try_reserve()");
460 template<
typename T >
461 class receiver :
public internal::untyped_receiver {
463 template<
typename,
typename >
friend struct internal::async_helpers;
468 __TBB_DEPRECATED typedef typename internal::async_helpers<T>::filtered_type filtered_type;
471 bool try_put(
const typename internal::async_helpers<T>::filtered_type& t ) {
472 return internal::untyped_receiver::try_put(t);
475 bool try_put(
const typename internal::async_helpers<T>::async_type& t ) {
476 return internal::untyped_receiver::try_put(t);
481 return internal::async_helpers<T>::try_put_task_wrapper_impl(
this,
p, is_async);
489 #else // __TBB_PREVIEW_ASYNC_MSG
492 template<
typename T >
523 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
524 __TBB_DEPRECATED typedef typename internal::edge_container<successor_type> built_successors_type;
526 __TBB_DEPRECATED typedef typename built_successors_type::edge_list_type successor_list_type;
536 template<
typename T >
551 if (!res)
return false;
572 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
573 __TBB_DEPRECATED typedef typename internal::edge_container<predecessor_type> built_predecessors_type;
574 __TBB_DEPRECATED typedef typename built_predecessors_type::edge_list_type predecessor_list_type;
578 __TBB_DEPRECATED virtual void copy_predecessors( predecessor_list_type & ) = 0;
589 #if __TBB_PREVIEW_OPENCL_NODE
594 #endif // __TBB_PREVIEW_ASYNC_MSG
639 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
640 __TBB_DEPRECATED typedef internal::edge_container<predecessor_type> built_predecessors_type;
641 __TBB_DEPRECATED typedef built_predecessors_type::edge_list_type predecessor_list_type;
642 built_predecessors_type &built_predecessors()
__TBB_override {
return my_built_predecessors; }
646 my_built_predecessors.add_edge(
s );
651 my_built_predecessors.delete_edge(
s);
656 my_built_predecessors.copy_edges(v);
661 return my_built_predecessors.edge_count();
683 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
686 built_predecessors_type my_built_predecessors;
700 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
701 my_built_predecessors.clear();
718 #if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING
719 template <
typename K,
typename T>
725 using interface11::sender;
726 using interface11::receiver;
727 using interface11::continue_receiver;
736 namespace interface11 {
741 #if __TBB_PREVIEW_ASYNC_MSG
746 template <
typename C,
typename N>
749 if (
begin) current_node = my_graph->my_nodes;
753 template <
typename C,
typename N>
756 return *operator->();
759 template <
typename C,
typename N>
764 template <
typename C,
typename N>
766 if (current_node) current_node = current_node->next;
771 namespace interface10 {
773 inline graph::graph() : my_nodes(NULL), my_nodes_last(NULL), my_task_arena(NULL) {
786 my_context(&use_this_context), my_nodes(NULL), my_nodes_last(NULL), my_task_arena(NULL) {
877 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
878 inline void graph::set_name(
const char *
name) {
885 namespace interface11 {
897 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
898 using internal::node_set;
902 template <
typename Output >
914 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
920 template<
typename Body >
932 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
933 template <
typename Body,
typename... Successors>
934 input_node(
const node_set<internal::order::preceding, Successors...>& successors, Body body )
935 :
input_node(successors.graph_reference(), body) {
936 make_edges(*
this, successors);
955 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
977 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
1067 template<
typename Body>
1073 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
1132 return (
new ( task::allocate_additional_child_of( *(this->
my_graph.
root_task()) ) )
1159 #if TBB_USE_SOURCE_NODE_AS_ALIAS
1160 template <
typename Output >
1164 template<
typename Body >
1170 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
1171 template <
typename Body,
typename... Successors>
1172 source_node(
const node_set<internal::order::preceding, Successors...>& successors, Body body )
1173 : input_node<Output>(successors, body) {
1177 #else // TBB_USE_SOURCE_NODE_AS_ALIAS
1178 template <
typename Output >
class
1180 __TBB_DEPRECATED_MSG(
"TBB Warning: tbb::flow::source_node is deprecated, use tbb::flow::input_node." )
1181 source_node : public graph_node, public sender< Output > {
1192 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
1198 template<
typename Body >
1200 :
graph_node(g), my_active(is_active), init_my_active(is_active),
1203 my_reserved(false), my_has_cached_item(false)
1205 my_successors.set_owner(
this);
1210 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
1211 template <
typename Body,
typename... Successors>
1212 source_node(
const node_set<internal::order::preceding, Successors...>& successors, Body body,
bool is_active =
true )
1213 :
source_node(successors.graph_reference(), body, is_active) {
1214 make_edges(*
this, successors);
1221 my_active(src.init_my_active),
1222 init_my_active(src.init_my_active), my_body( src.my_init_body->clone() ), my_init_body(src.my_init_body->clone() ),
1223 my_reserved(false), my_has_cached_item(false)
1225 my_successors.set_owner(
this);
1233 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
1242 my_successors.register_successor(r);
1251 my_successors.remove_successor(r);
1255 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
1257 built_successors_type &built_successors()
__TBB_override {
return my_successors.built_successors(); }
1259 void internal_add_built_successor( successor_type &r)
__TBB_override {
1261 my_successors.internal_add_built_successor(r);
1264 void internal_delete_built_successor( successor_type &r)
__TBB_override {
1266 my_successors.internal_delete_built_successor(r);
1271 return my_successors.successor_count();
1276 my_successors.copy_successors(v);
1286 if ( my_has_cached_item ) {
1288 my_has_cached_item =
false;
1300 if ( my_reserved ) {
1304 if ( my_has_cached_item ) {
1317 __TBB_ASSERT( my_reserved && my_has_cached_item,
"releasing non-existent reservation" );
1318 my_reserved =
false;
1319 if(!my_successors.empty())
1327 __TBB_ASSERT( my_reserved && my_has_cached_item,
"consuming non-existent reservation" );
1328 my_reserved =
false;
1329 my_has_cached_item =
false;
1330 if ( !my_successors.empty() ) {
1340 if (!my_successors.empty())
1344 template<
typename Body>
1350 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
1352 my_successors.built_successors().sender_extract(*
this);
1353 my_active = init_my_active;
1354 my_reserved =
false;
1355 if(my_has_cached_item) my_has_cached_item =
false;
1363 my_active = init_my_active;
1365 if(my_has_cached_item) {
1366 my_has_cached_item =
false;
1392 if ( my_reserved ) {
1395 if ( !my_has_cached_item ) {
1397 bool r = (*my_body)(my_cached_item);
1400 my_has_cached_item =
true;
1403 if ( my_has_cached_item ) {
1417 return (
new ( task::allocate_additional_child_of( *(this->my_graph.root_task()) ) )
1432 if ( !try_reserve_apply_body(v) )
1435 task *last_task = my_successors.try_put_task(v);
1443 #endif // TBB_USE_SOURCE_NODE_AS_ALIAS
1450 #if TBB_DEPRECATED_FLOW_NODE_ALLOCATOR
1457 #if TBB_DEPRECATED_FLOW_NODE_ALLOCATOR
1464 "Allocator template parameter for flow graph nodes is deprecated and will be removed. "
1465 "Specify TBB_DEPRECATED_FLOW_NODE_ALLOCATOR to temporary enable the deprecated interface."
1477 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
1478 typedef typename input_impl_type::predecessor_list_type predecessor_list_type;
1479 typedef typename fOutput_type::successor_list_type successor_list_type;
1487 template<
typename Body >
1500 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES && __TBB_CPP11_PRESENT
1501 template <
typename Body>
1504 #endif // __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES && __TBB_CPP11_PRESENT
1506 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
1507 template <
typename Body,
typename... Args>
1511 make_edges_in_order(nodes, *
this);
1514 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
1515 template <
typename Body,
typename... Args>
1518 #endif // __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
1519 #endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
1530 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
1536 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
1539 successors().built_successors().sender_extract(*
this);
1566 template<
typename Input,
typename Output,
typename Policy =
queueing,
1573 typename internal::wrap_tuple_elements<
1574 tbb::flow::tuple_size<Output>::value,
1575 internal::multifunction_output,
1579 #if TBB_DEPRECATED_FLOW_NODE_ALLOCATOR
1582 cache_aligned_allocator<Input>
1585 #if TBB_DEPRECATED_FLOW_NODE_ALLOCATOR
1592 "Allocator template parameter for flow graph nodes is deprecated and will be removed. "
1593 "Specify TBB_DEPRECATED_FLOW_NODE_ALLOCATOR to temporary enable the deprecated interface."
1609 template<
typename Body>
1618 tbb::internal::fgt_multioutput_node_with_body<N>(
1619 CODEPTR(), tbb::internal::FLOW_MULTIFUNCTION_NODE,
1625 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES && __TBB_CPP11_PRESENT
1626 template <
typename Body>
1629 #endif // TBB_PREVIEW_FLOW_GRAPH_PRIORITIES && __TBB_CPP11_PRESENT
1631 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
1632 template <
typename Body,
typename... Args>
1636 make_edges_in_order(nodes, *
this);
1639 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
1640 template <
typename Body,
typename... Args>
1643 #endif // __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
1644 #endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
1648 tbb::internal::fgt_multioutput_node_with_body<N>(
CODEPTR(), tbb::internal::FLOW_MULTIFUNCTION_NODE,
1653 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
1659 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
1662 input_impl_type::extract();
1672 template<
typename TupleType,
typename Allocator=__TBB_DEFAULT_NODE_ALLOCATOR(TupleType)>
1678 #if TBB_DEPRECATED_FLOW_NODE_ALLOCATOR
1683 "Allocator template parameter for flow graph nodes is deprecated and will be removed. "
1684 "Specify TBB_DEPRECATED_FLOW_NODE_ALLOCATOR to temporary enable the deprecated interface."
1687 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
1689 typedef typename base_type::predecessor_list_type predecessor_list_type;
1691 typedef typename predecessor_cache_type::built_predecessors_type built_predecessors_type;
1704 tbb::internal::fgt_multioutput_node<N>(
CODEPTR(), tbb::internal::FLOW_SPLIT_NODE, &this->
my_graph,
1708 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
1709 template <
typename... Args>
1711 make_edges_in_order(nodes, *
this);
1719 tbb::internal::fgt_multioutput_node<N>(
CODEPTR(), tbb::internal::FLOW_SPLIT_NODE, &this->
my_graph,
1723 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
1747 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
1761 built_predecessors_type &built_predecessors()
__TBB_override {
return my_predessors; }
1764 built_predecessors_type my_predessors;
1772 template <
typename Output,
typename Policy =
internal::Policy<
void> >
1784 template <
typename Body >
1800 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES && __TBB_CPP11_PRESENT
1801 template <
typename Body>
1806 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
1807 template <
typename Body,
typename... Args>
1811 make_edges_in_order(nodes, *
this);
1813 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
1814 template <
typename Body,
typename... Args>
1817 #endif // __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
1818 #endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
1821 template <
typename Body >
1823 graph &g,
int number_of_predecessors,
1837 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES && __TBB_CPP11_PRESENT
1838 template <
typename Body>
1840 :
continue_node(g, number_of_predecessors, body, Policy(), priority) {}
1843 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
1844 template <
typename Body,
typename... Args>
1845 continue_node(
const node_set<Args...>& nodes,
int number_of_predecessors,
1848 make_edges_in_order(nodes, *
this);
1851 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
1852 template <
typename Body,
typename... Args>
1853 continue_node(
const node_set<Args...>& nodes,
int number_of_predecessors,
1855 :
continue_node(nodes, number_of_predecessors, body, Policy(), priority) {}
1868 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
1874 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
1876 input_impl_type::my_built_predecessors.receiver_extract(*
this);
1877 successors().built_successors().sender_extract(*
this);
1885 using input_impl_type::try_put_task;
1896 template <
typename T>
1903 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
1909 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
1910 internal::edge_container<predecessor_type> my_built_predecessors;
1921 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
1922 template <
typename... Args>
1924 make_edges_in_order(nodes, *
this);
1937 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
1955 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
1976 typedef typename receiver<T>::built_predecessors_type built_predecessors_type;
1978 built_predecessors_type &built_predecessors()
__TBB_override {
return my_built_predecessors; }
1982 my_built_predecessors.add_edge(
p);
1987 my_built_predecessors.delete_edge(
p);
1992 return my_built_predecessors.edge_count();
1995 void copy_predecessors(predecessor_list_type &v)
__TBB_override {
1997 my_built_predecessors.copy_edges(v);
2001 my_built_predecessors.receiver_extract(*
this);
2026 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
2027 my_built_predecessors.clear();
2035 template <
typename T,
typename Allocator=__TBB_DEFAULT_NODE_ALLOCATOR(T) >
2038 #if TBB_DEPRECATED_FLOW_NODE_ALLOCATOR
2044 #if TBB_DEPRECATED_FLOW_NODE_ALLOCATOR
2055 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
2059 #if !TBB_DEPRECATED_FLOW_NODE_ALLOCATOR
2062 "Allocator template parameter for flow graph nodes is deprecated and will be removed. "
2063 "Specify TBB_DEPRECATED_FLOW_NODE_ALLOCATOR to temporary enable the deprecated interface."
2071 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
2072 internal::edge_container<predecessor_type> my_built_predecessors;
2078 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
2079 , add_blt_succ, del_blt_succ,
2080 add_blt_pred, del_blt_pred,
2081 blt_succ_cnt, blt_pred_cnt,
2082 blt_succ_cpy, blt_pred_cpy
2090 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
2097 successor_list_type *svec;
2098 predecessor_list_type *pvec;
2107 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
2110 ,
elem(const_cast<T*>(&e)) ,
ltask(NULL)
2125 template<
typename derived_type>
2129 buffer_operation *tmp = NULL;
2130 bool try_forwarding =
false;
2133 op_list = op_list->next;
2134 switch (tmp->type) {
2143 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
2145 case add_blt_succ: internal_add_built_succ(tmp);
break;
2146 case del_blt_succ: internal_del_built_succ(tmp);
break;
2147 case add_blt_pred: internal_add_built_pred(tmp);
break;
2148 case del_blt_pred: internal_del_built_pred(tmp);
break;
2149 case blt_succ_cnt: internal_succ_cnt(tmp);
break;
2150 case blt_pred_cnt: internal_pred_cnt(tmp);
break;
2151 case blt_succ_cpy: internal_copy_succs(tmp);
break;
2152 case blt_pred_cpy: internal_copy_preds(tmp);
break;
2161 forwarder_busy =
true;
2163 forward_task_bypass<class_type>(*
this);
2175 return op_data.ltask;
2190 task *last_task = NULL;
2193 op_data.ltask = NULL;
2216 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
2221 virtual void internal_add_built_succ(buffer_operation *op) {
2226 virtual void internal_del_built_succ(buffer_operation *op) {
2231 typedef typename receiver<T>::built_predecessors_type built_predecessors_type;
2233 built_predecessors_type &built_predecessors()
__TBB_override {
return my_built_predecessors; }
2235 virtual void internal_add_built_pred(buffer_operation *op) {
2236 my_built_predecessors.add_edge(*(op->p));
2240 virtual void internal_del_built_pred(buffer_operation *op) {
2241 my_built_predecessors.delete_edge(*(op->p));
2245 virtual void internal_succ_cnt(buffer_operation *op) {
2250 virtual void internal_pred_cnt(buffer_operation *op) {
2251 op->cnt_val = my_built_predecessors.edge_count();
2255 virtual void internal_copy_succs(buffer_operation *op) {
2260 virtual void internal_copy_preds(buffer_operation *op) {
2261 my_built_predecessors.copy_edges(*(op->pvec));
2290 template<
typename derived_type>
2294 if (this->
my_reserved || !derived->is_item_valid()) {
2296 this->forwarder_busy =
false;
2300 task * last_task = NULL;
2302 for (; counter > 0 && derived->is_item_valid(); --counter)
2303 derived->try_put_and_add_task(last_task);
2305 op->ltask = last_task;
2306 if (last_task && !counter) {
2361 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
2362 template <
typename... Args>
2364 make_edges_in_order(nodes, *
this);
2379 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
2392 buffer_operation op_data(
reg_succ);
2399 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
2401 buffer_operation op_data(add_blt_succ);
2407 buffer_operation op_data(del_blt_succ);
2413 buffer_operation op_data(add_blt_pred);
2419 buffer_operation op_data(del_blt_pred);
2425 buffer_operation op_data(blt_pred_cnt);
2427 return op_data.cnt_val;
2431 buffer_operation op_data(blt_succ_cnt);
2433 return op_data.cnt_val;
2436 void copy_predecessors( predecessor_list_type &v )
__TBB_override {
2437 buffer_operation op_data(blt_pred_cpy);
2443 buffer_operation op_data(blt_succ_cpy);
2454 r.remove_predecessor(*
this);
2455 buffer_operation op_data(
rem_succ);
2469 buffer_operation op_data(
req_item);
2480 buffer_operation op_data(
res_item);
2490 buffer_operation op_data(
rel_res);
2499 buffer_operation op_data(
con_res);
2512 buffer_operation op_data(t,
put_item);
2536 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
2539 my_built_predecessors.receiver_extract(*
this);
2550 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
2551 my_built_predecessors.clear();
2559 template <
typename T,
typename Allocator=__TBB_DEFAULT_NODE_ALLOCATOR(T) >
2561 #if !TBB_DEPRECATED_FLOW_NODE_ALLOCATOR
2564 "Allocator template parameter for flow graph nodes is deprecated and will be removed. "
2565 "Specify TBB_DEPRECATED_FLOW_NODE_ALLOCATOR to temporary enable the deprecated interface."
2582 task *new_task = this->my_successors.try_put_task(this->
front());
2632 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
2633 template <
typename... Args>
2635 make_edges_in_order(nodes, *
this);
2646 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
2659 template<
typename T,
typename Allocator=__TBB_DEFAULT_NODE_ALLOCATOR(T) >
2665 #if !TBB_DEPRECATED_FLOW_NODE_ALLOCATOR
2668 "Allocator template parameter for flow graph nodes is deprecated and will be removed. "
2669 "Specify TBB_DEPRECATED_FLOW_NODE_ALLOCATOR to temporary enable the deprecated interface."
2678 template<
typename Sequencer >
2686 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
2687 template <
typename Sequencer,
typename... Args>
2690 make_edges_in_order(nodes, *
this);
2705 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
2717 size_type tag = (*my_sequencer)(*(op->elem));
2718 #if !TBB_DEPRECATED_SEQUENCER_DUPLICATES
2726 size_t new_tail = (tag+1 > this->
my_tail) ? tag+1 : this->
my_tail;
2740 template<
typename T,
typename Compare = std::less<T>,
typename Allocator=__TBB_DEFAULT_NODE_ALLOCATOR(T)>
2743 #if !TBB_DEPRECATED_FLOW_NODE_ALLOCATOR
2746 "Allocator template parameter for flow graph nodes is deprecated and will removed in the future. "
2747 "To temporary enable the deprecated interface specify TBB_ENABLE_DEPRECATED_NODE_ALLOCATOR."
2765 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
2766 template <
typename... Args>
2769 make_edges_in_order(nodes, *
this);
2782 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
2821 *(op->elem) =
prio();
2834 *(op->elem) =
prio();
2866 task * new_task = this->my_successors.try_put_task(this->
prio());
2933 size_type cur_pos =
mark;
2950 while (child <
mark) {
2963 child = (cur_pos<<1)+1;
2970 namespace interface11 {
2976 template<
typename T,
typename DecrementType=continue_msg >
2977 class limiter_node :
public graph_node,
public receiver< T >,
public sender< T > {
2983 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
3013 bool reserved =
false;
3035 task *rtask =
new ( task::allocate_additional_child_of( *(this->my_graph.root_task()) ) )
3053 task *rtask =
new ( task::allocate_additional_child_of( *(this->my_graph.root_task()) ) )
3071 if( delta > 0 &&
size_t(delta) >
my_count )
3086 CODEPTR(), tbb::internal::FLOW_LIMITER_NODE, &this->my_graph,
3095 #if TBB_DEPRECATED_LIMITER_NODE_CONSTRUCTOR
3097 "Deprecated interface of the limiter node can be used only in conjunction "
3098 "with continue_msg as the type of DecrementType template parameter." );
3099 #endif // Check for incompatible interface
3107 init_decrement_predecessors(num_decrement_predecessors),
3108 decrement(num_decrement_predecessors)) {
3112 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
3113 template <
typename... Args>
3114 limiter_node(
const node_set<Args...>& nodes,
size_t threshold)
3116 make_edges_in_order(nodes, *
this);
3126 init_decrement_predecessors(src.init_decrement_predecessors),
3127 decrement(src.init_decrement_predecessors)) {
3131 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
3145 task*
task =
new ( task::allocate_additional_child_of( *(this->my_graph.root_task()) ) )
3156 r.remove_predecessor(*
this);
3161 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
3189 void copy_predecessors(predecessor_list_type &v)
__TBB_override {
3206 task*
task =
new ( task::allocate_additional_child_of( *(this->my_graph.root_task()) ) )
3240 rtask =
new ( task::allocate_additional_child_of( *(this->my_graph.root_task()) ) )
3280 template<
typename OutputTuple,
typename JP=queueing>
class join_node;
3282 template<
typename OutputTuple>
3291 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_JOIN_NODE_RESERVING, &this->my_graph,
3295 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
3296 template <
typename... Args>
3298 make_edges_in_order(nodes, *
this);
3303 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_JOIN_NODE_RESERVING, &this->my_graph,
3307 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
3315 template<
typename OutputTuple>
3324 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_JOIN_NODE_QUEUEING, &this->my_graph,
3328 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
3329 template <
typename... Args>
3331 make_edges_in_order(nodes, *
this);
3336 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_JOIN_NODE_QUEUEING, &this->my_graph,
3340 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
3350 template<
typename OutputTuple,
typename K,
typename KHash>
3352 key_matching_port, OutputTuple, key_matching<K,KHash> > {
3360 #if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING
3363 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
3364 template <
typename... Args>
3367 make_edges_in_order(nodes, *
this);
3373 template<
typename __TBB_B0,
typename __TBB_B1>
3375 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
3378 template<
typename __TBB_B0,
typename __TBB_B1,
typename __TBB_B2>
3380 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
3383 template<
typename __TBB_B0,
typename __TBB_B1,
typename __TBB_B2,
typename __TBB_B3>
3385 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
3388 template<
typename __TBB_B0,
typename __TBB_B1,
typename __TBB_B2,
typename __TBB_B3,
typename __TBB_B4>
3391 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
3394 #if __TBB_VARIADIC_MAX >= 6
3395 template<
typename __TBB_B0,
typename __TBB_B1,
typename __TBB_B2,
typename __TBB_B3,
typename __TBB_B4,
3399 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
3403 #if __TBB_VARIADIC_MAX >= 7
3404 template<
typename __TBB_B0,
typename __TBB_B1,
typename __TBB_B2,
typename __TBB_B3,
typename __TBB_B4,
3405 typename __TBB_B5,
typename __TBB_B6>
3408 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
3412 #if __TBB_VARIADIC_MAX >= 8
3413 template<
typename __TBB_B0,
typename __TBB_B1,
typename __TBB_B2,
typename __TBB_B3,
typename __TBB_B4,
3414 typename __TBB_B5,
typename __TBB_B6,
typename __TBB_B7>
3416 __TBB_B7 b7) :
unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7) {
3417 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
3421 #if __TBB_VARIADIC_MAX >= 9
3422 template<
typename __TBB_B0,
typename __TBB_B1,
typename __TBB_B2,
typename __TBB_B3,
typename __TBB_B4,
3423 typename __TBB_B5,
typename __TBB_B6,
typename __TBB_B7,
typename __TBB_B8>
3425 __TBB_B7 b7, __TBB_B8 b8) :
unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7, b8) {
3426 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
3430 #if __TBB_VARIADIC_MAX >= 10
3431 template<
typename __TBB_B0,
typename __TBB_B1,
typename __TBB_B2,
typename __TBB_B3,
typename __TBB_B4,
3432 typename __TBB_B5,
typename __TBB_B6,
typename __TBB_B7,
typename __TBB_B8,
typename __TBB_B9>
3434 __TBB_B7 b7, __TBB_B8 b8, __TBB_B9 b9) :
unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9) {
3435 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
3440 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
3441 template <
typename... Args,
typename... Bodies>
3443 :
join_node(nodes.graph_reference(), bodies...) {
3444 make_edges_in_order(nodes, *
this);
3449 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
3453 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
3465 template<
typename T0,
typename T1=null_type,
typename T2=null_type,
typename T3=null_type,
3466 typename T4=null_type,
typename T5=null_type,
typename T6=null_type,
3470 template<
typename T0>
3473 static const int N = 1;
3479 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3483 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
3484 template <
typename... Args>
3486 make_edges_in_order(nodes, *
this);
3492 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3496 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
3503 template<
typename T0,
typename T1>
3506 static const int N = 2;
3512 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3516 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
3517 template <
typename... Args>
3519 make_edges_in_order(nodes, *
this);
3525 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3529 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
3536 template<
typename T0,
typename T1,
typename T2>
3539 static const int N = 3;
3545 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3549 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
3550 template <
typename... Args>
3552 make_edges_in_order(nodes, *
this);
3558 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3562 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
3569 template<
typename T0,
typename T1,
typename T2,
typename T3>
3572 static const int N = 4;
3578 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3582 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
3583 template <
typename... Args>
3585 make_edges_in_order(nodes, *
this);
3591 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3595 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
3602 template<
typename T0,
typename T1,
typename T2,
typename T3,
typename T4>
3605 static const int N = 5;
3611 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3615 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
3616 template <
typename... Args>
3618 make_edges_in_order(nodes, *
this);
3624 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3628 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
3635 #if __TBB_VARIADIC_MAX >= 6
3636 template<
typename T0,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
3637 class indexer_node<T0, T1, T2, T3, T4, T5> :
public internal::unfolded_indexer_node<tuple<T0, T1, T2, T3, T4, T5> > {
3639 static const int N = 6;
3645 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3649 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
3650 template <
typename... Args>
3652 make_edges_in_order(nodes, *
this);
3658 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3662 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
3668 #endif //variadic max 6
3670 #if __TBB_VARIADIC_MAX >= 7
3671 template<
typename T0,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
3673 class indexer_node<T0, T1, T2, T3, T4, T5, T6> :
public internal::unfolded_indexer_node<tuple<T0, T1, T2, T3, T4, T5, T6> > {
3675 static const int N = 7;
3681 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3685 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
3686 template <
typename... Args>
3688 make_edges_in_order(nodes, *
this);
3694 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3698 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
3704 #endif //variadic max 7
3706 #if __TBB_VARIADIC_MAX >= 8
3707 template<
typename T0,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
3708 typename T6,
typename T7>
3709 class indexer_node<T0, T1, T2, T3, T4, T5, T6, T7> :
public internal::unfolded_indexer_node<tuple<T0, T1, T2, T3, T4, T5, T6, T7> > {
3711 static const int N = 8;
3717 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3721 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
3722 template <
typename... Args>
3724 make_edges_in_order(nodes, *
this);
3730 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3734 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
3740 #endif //variadic max 8
3742 #if __TBB_VARIADIC_MAX >= 9
3743 template<
typename T0,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
3744 typename T6,
typename T7,
typename T8>
3745 class indexer_node<T0, T1, T2, T3, T4, T5, T6, T7, T8> :
public internal::unfolded_indexer_node<tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8> > {
3747 static const int N = 9;
3753 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3757 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
3758 template <
typename... Args>
3760 make_edges_in_order(nodes, *
this);
3766 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3770 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
3776 #endif //variadic max 9
3778 #if __TBB_VARIADIC_MAX >= 10
3779 template<
typename T0,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
3780 typename T6,
typename T7,
typename T8,
typename T9>
3783 static const int N = 10;
3785 typedef tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>
InputTuple;
3786 typedef typename internal::tagged_msg<size_t, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> output_type;
3789 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3793 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
3794 template <
typename... Args>
3796 make_edges_in_order(nodes, *
this);
3802 tbb::internal::fgt_multiinput_node<N>(
CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
3806 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
3812 #endif //variadic max 10
3814 #if __TBB_PREVIEW_ASYNC_MSG
3817 template<
typename T >
3820 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
3821 s.internal_add_built_predecessor(
p);
3822 p.internal_add_built_successor(
s);
3824 p.register_successor(
s );
3829 template<
typename T >
3834 #if __TBB_PREVIEW_ASYNC_MSG
3835 template<
typename TS,
typename TR,
3842 template<
typename T >
3843 inline void make_edge( sender<T> &
p, receiver<typename T::async_msg_data_type> &
s ) {
3847 template<
typename T >
3848 inline void make_edge( sender<typename T::async_msg_data_type> &
p, receiver<T> &
s ) {
3852 #endif // __TBB_PREVIEW_ASYNC_MSG
3854 #if __TBB_FLOW_GRAPH_CPP11_FEATURES
3856 template<
typename T,
typename V,
3857 typename =
typename T::output_ports_type,
typename =
typename V::input_ports_type >
3859 make_edge(get<0>(output.output_ports()), get<0>(input.input_ports()));
3863 template<
typename T,
typename R,
3864 typename =
typename T::output_ports_type >
3866 make_edge(get<0>(output.output_ports()), input);
3870 template<
typename S,
typename V,
3871 typename =
typename V::input_ports_type >
3873 make_edge(output, get<0>(input.input_ports()));
3877 #if __TBB_PREVIEW_ASYNC_MSG
3880 template<
typename T >
3883 p.remove_successor(
s );
3884 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
3886 p.internal_delete_built_successor(
s);
3887 s.internal_delete_built_predecessor(
p);
3893 template<
typename T >
3898 #if __TBB_PREVIEW_ASYNC_MSG
3899 template<
typename TS,
typename TR,
3906 template<
typename T >
3907 inline void remove_edge( sender<T> &
p, receiver<typename T::async_msg_data_type> &
s ) {
3911 template<
typename T >
3912 inline void remove_edge( sender<typename T::async_msg_data_type> &
p, receiver<T> &
s ) {
3915 #endif // __TBB_PREVIEW_ASYNC_MSG
3917 #if __TBB_FLOW_GRAPH_CPP11_FEATURES
3919 template<
typename T,
typename V,
3920 typename =
typename T::output_ports_type,
typename =
typename V::input_ports_type >
3922 remove_edge(get<0>(output.output_ports()), get<0>(input.input_ports()));
3926 template<
typename T,
typename R,
3927 typename =
typename T::output_ports_type >
3929 remove_edge(get<0>(output.output_ports()), input);
3932 template<
typename S,
typename V,
3933 typename =
typename V::input_ports_type >
3939 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
3940 template<
typename C >
3941 template<
typename S >
3942 void internal::edge_container<C>::sender_extract(
S &
s ) {
3943 edge_list_type e = built_edges;
3944 for (
typename edge_list_type::iterator i = e.begin(); i != e.end(); ++i ) {
3949 template<
typename C >
3950 template<
typename R >
3951 void internal::edge_container<C>::receiver_extract( R &r ) {
3952 edge_list_type e = built_edges;
3953 for (
typename edge_list_type::iterator i = e.begin(); i != e.end(); ++i ) {
3960 template<
typename Body,
typename Node >
3962 return n.template copy_function_object<Body>();
3965 #if __TBB_FLOW_GRAPH_CPP11_FEATURES
3970 template<
typename... InputTypes,
typename... OutputTypes>
3981 static const size_t NUM_INPUTS =
sizeof...(InputTypes);
3982 static const size_t NUM_OUTPUTS =
sizeof...(OutputTypes);
3988 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
3999 template<
typename T1,
typename T2>
4003 my_input_ports = tbb::internal::make_unique<input_ports_type>(std::forward<T1>(input_ports_tuple));
4004 my_output_ports = tbb::internal::make_unique<output_ports_type>(std::forward<T2>(output_ports_tuple));
4010 template<
typename... NodeTypes >
4013 template<
typename... NodeTypes >
4016 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
4023 __TBB_ASSERT(my_input_ports,
"input ports not set, call set_external_ports to set input ports");
4024 return *my_input_ports;
4028 __TBB_ASSERT(my_output_ports,
"output ports not set, call set_external_ports to set output ports");
4029 return *my_output_ports;
4032 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
4034 __TBB_ASSERT(
false,
"Current composite_node implementation does not support extract");
4040 template<
typename... InputTypes>
4047 static const size_t NUM_INPUTS =
sizeof...(InputTypes);
4053 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
4064 template<
typename T>
4068 my_input_ports = tbb::internal::make_unique<input_ports_type>(std::forward<T>(input_ports_tuple));
4073 template<
typename... NodeTypes >
4076 template<
typename... NodeTypes >
4079 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
4086 __TBB_ASSERT(my_input_ports,
"input ports not set, call set_external_ports to set input ports");
4087 return *my_input_ports;
4090 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
4092 __TBB_ASSERT(
false,
"Current composite_node implementation does not support extract");
4099 template<
typename... OutputTypes>
4106 static const size_t NUM_OUTPUTS =
sizeof...(OutputTypes);
4112 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
4123 template<
typename T>
4127 my_output_ports = tbb::internal::make_unique<output_ports_type>(std::forward<T>(output_ports_tuple));
4132 template<
typename... NodeTypes >
4135 template<
typename... NodeTypes >
4138 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
4145 __TBB_ASSERT(my_output_ports,
"output ports not set, call set_external_ports to set output ports");
4146 return *my_output_ports;
4149 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
4151 __TBB_ASSERT(
false,
"Current composite_node implementation does not support extract");
4157 #endif // __TBB_FLOW_GRAPH_CPP11_FEATURES
4161 template<
typename Gateway>
4175 template<
typename Input,
typename Ports,
typename Gateway,
typename Body>
4197 namespace interface11 {
4200 template <
typename Input,
typename Output,
4206 #if !TBB_DEPRECATED_FLOW_NODE_ALLOCATOR
4209 "Allocator template parameter for flow graph nodes is deprecated and will removed in the future. "
4210 "To temporary enable the deprecated interface specify TBB_ENABLE_DEPRECATED_NODE_ALLOCATOR."
4244 my_node->my_graph.reserve_wait();
4248 my_node->my_graph.release_wait();
4254 return my_node->try_put_impl(i);
4270 bool is_at_least_one_put_successful = port_successors.gather_successful_try_puts(i, tasks);
4272 "Return status is inconsistent with the method operation." );
4274 while( !tasks.
empty() ) {
4278 return is_at_least_one_put_successful;
4282 template<
typename Body>
4294 tbb::internal::fgt_multioutput_node_with_body<1>(
4295 CODEPTR(), tbb::internal::FLOW_ASYNC_NODE,
4297 this->output_ports(), this->my_body
4301 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES && __TBB_CPP11_PRESENT
4302 template <
typename Body,
typename... Args>
4305 #endif // __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
4307 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
4308 template <
typename Body,
typename... Args>
4310 const node_set<Args...>& nodes,
size_t concurrency, Body body,
4313 make_edges_in_order(nodes, *
this);
4316 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
4317 template <
typename Body,
typename... Args>
4319 : async_node(nodes,
concurrency, body, Policy(), priority) {}
4320 #endif // __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
4321 #endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
4325 static_cast<async_body_base_type*
>(this->my_init_body->get_body_ptr())->set_gateway(&my_gateway);
4327 tbb::internal::fgt_multioutput_node_with_body<1>(
CODEPTR(), tbb::internal::FLOW_ASYNC_NODE,
4329 this->output_ports(), this->my_body );
4336 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
4346 return internal::output_port<0>(*this).register_successor(r);
4351 return internal::output_port<0>(*this).remove_successor(r);
4354 template<
typename Body>
4358 mfn_body_type &body_ref = *this->my_body;
4363 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
4364 typedef typename internal::edge_container<successor_type> built_successors_type;
4366 typedef typename built_successors_type::edge_list_type successor_list_type;
4368 return internal::output_port<0>(*this).built_successors();
4371 void internal_add_built_successor( successor_type &r )
__TBB_override {
4372 internal::output_port<0>(*this).internal_add_built_successor(r);
4375 void internal_delete_built_successor( successor_type &r )
__TBB_override {
4376 internal::output_port<0>(*this).internal_delete_built_successor(r);
4380 internal::output_port<0>(*this).copy_successors(l);
4384 return internal::output_port<0>(*this).successor_count();
4391 base_type::reset_node(f);
4395 #if __TBB_PREVIEW_STREAMING_NODE
4397 #endif // __TBB_PREVIEW_STREAMING_NODE
4401 template<
typename T >
4408 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
4416 my_successors.set_owner(
this );
4421 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
4422 template <
typename... Args>
4424 make_edges_in_order(nodes, *
this);
4432 my_successors.set_owner(
this );
4439 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
4449 bool ret =
s.try_put( my_buffer );
4452 my_successors.register_successor(
s );
4458 task *rtask =
new ( task::allocate_additional_child_of( *( my_graph.root_task() ) ) )
4464 my_successors.register_successor(
s );
4471 my_successors.remove_successor(
s);
4475 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
4476 built_predecessors_type &built_predecessors()
__TBB_override {
return my_built_predecessors; }
4477 built_successors_type &built_successors()
__TBB_override {
return my_successors.built_successors(); }
4479 void internal_add_built_successor( successor_type &
s)
__TBB_override {
4481 my_successors.internal_add_built_successor(
s);
4484 void internal_delete_built_successor( successor_type &
s)
__TBB_override {
4486 my_successors.internal_delete_built_successor(
s);
4491 return my_successors.successor_count();
4496 my_successors.copy_successors(v);
4499 void internal_add_built_predecessor( predecessor_type &
p)
__TBB_override {
4501 my_built_predecessors.add_edge(
p);
4504 void internal_delete_built_predecessor( predecessor_type &
p)
__TBB_override {
4506 my_built_predecessors.delete_edge(
p);
4511 return my_built_predecessors.edge_count();
4514 void copy_predecessors( predecessor_list_type &v )
__TBB_override {
4516 my_built_predecessors.copy_edges(v);
4520 my_buffer_is_valid =
false;
4521 built_successors().sender_extract(*
this);
4522 built_predecessors().receiver_extract(*
this);
4529 if ( my_buffer_is_valid ) {
4549 return my_buffer_is_valid;
4554 my_buffer_is_valid =
false;
4564 return try_put_task_impl(v);
4569 my_buffer_is_valid =
true;
4583 o(owner),
s(succ) {};
4586 if (!
s.register_predecessor(o)) {
4587 o.register_successor(
s);
4598 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
4599 internal::edge_container<predecessor_type> my_built_predecessors;
4606 my_buffer_is_valid =
false;
4608 my_successors.clear();
4613 template<
typename T >
4629 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
4630 template <
typename... Args>
4632 make_edges_in_order(nodes, *
this);
4643 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
4655 return this->my_buffer_is_valid ? NULL : this->try_put_task_impl(v);
4666 using interface11::graph;
4667 using interface11::graph_node;
4668 using interface11::continue_msg;
4669 using interface11::source_node;
4670 using interface11::input_node;
4671 using interface11::function_node;
4672 using interface11::multifunction_node;
4673 using interface11::split_node;
4675 using interface11::indexer_node;
4676 using interface11::internal::tagged_msg;
4679 using interface11::continue_node;
4680 using interface11::overwrite_node;
4681 using interface11::write_once_node;
4682 using interface11::broadcast_node;
4683 using interface11::buffer_node;
4684 using interface11::queue_node;
4685 using interface11::sequencer_node;
4686 using interface11::priority_queue_node;
4687 using interface11::limiter_node;
4688 using namespace interface11::internal::graph_policy_namespace;
4689 using interface11::join_node;
4695 #if __TBB_FLOW_GRAPH_CPP11_FEATURES
4696 using interface11::composite_node;
4698 using interface11::async_node;
4699 #if __TBB_PREVIEW_ASYNC_MSG
4700 using interface11::async_msg;
4702 #if __TBB_PREVIEW_STREAMING_NODE
4705 #endif // __TBB_PREVIEW_STREAMING_NODE
4706 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
4711 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
4712 using interface11::internal::follows;
4713 using interface11::internal::precedes;
4714 using interface11::internal::make_node_set;
4715 using interface11::internal::make_edges;
4724 #undef __TBB_PFG_RESET_ARG
4726 #undef __TBB_DEFAULT_NODE_ALLOCATOR
4729 #undef __TBB_flow_graph_H_include_area
4731 #if TBB_USE_THREADING_TOOLS && TBB_PREVIEW_FLOW_GRAPH_TRACE && ( __linux__ || __APPLE__ )
4732 #undef __TBB_NOINLINE_SYM
4735 #endif // __TBB_flow_graph_H