1.. _Flow_Graph_Single_Vs_Broadcast: 2 3Flow Graph Basics: Single-push vs. Broadcast-push 4================================================= 5 6 7Nodes in the |full_name| flow graph 8communicate by pushing and pulling messages. Two policies for pushing 9messages are used, depending on the type of the node: 10 11 12- **single-push**: No matter how many successors to the node exist and 13 are able to accept a message, each message will be only sent to one 14 successor. 15- **broadcast-push**: A message will be pushed to every successor which 16 is connected to the node by an edge in push mode, and which accepts 17 the message. 18 19 20The following code demonstrates this difference: 21 22 23:: 24 25 26 using namespace oneapi::tbb::flow; 27 28 29 std::atomic<size_t> g_cnt; 30 31 32 struct fn_body1 { 33 std::atomic<size_t> &body_cnt; 34 fn_body1(std::atomic<size_t> &b_cnt) : body_cnt(b_cnt) {} 35 continue_msg operator()( continue_msg /*dont_care*/) { 36 ++g_cnt; 37 ++body_cnt; 38 return continue_msg(); 39 } 40 }; 41 42 43 void run_example1() { // example for Flow_Graph_Single_Vs_Broadcast.xml 44 graph g; 45 std::atomic<size_t> b1; // local counts 46 std::atomic<size_t> b2; // for each function _node body 47 std::atomic<size_t> b3; // 48 function_node<continue_msg> f1(g,serial,fn_body1(b1)); 49 function_node<continue_msg> f2(g,serial,fn_body1(b2)); 50 function_node<continue_msg> f3(g,serial,fn_body1(b3)); 51 buffer_node<continue_msg> buf1(g); 52 // 53 // single-push policy 54 // 55 g_cnt = b1 = b2 = b3 = 0; 56 make_edge(buf1,f1); 57 make_edge(buf1,f2); 58 make_edge(buf1,f3); 59 buf1.try_put(continue_msg()); 60 buf1.try_put(continue_msg()); 61 buf1.try_put(continue_msg()); 62 g.wait_for_all(); 63 printf( "after single-push test, g_cnt == %d, b1==%d, b2==%d, b3==%d\n", (int)g_cnt, (int)b1, (int)b2, (int)b3); 64 remove_edge(buf1,f1); 65 remove_edge(buf1,f2); 66 remove_edge(buf1,f3); 67 // 68 // broadcast-push policy 69 // 70 broadcast_node<continue_msg> bn(g); 71 g_cnt = b1 = b2 = b3 = 0; 72 make_edge(bn,f1); 73 make_edge(bn,f2); 74 make_edge(bn,f3); 75 bn.try_put(continue_msg()); 76 bn.try_put(continue_msg()); 77 bn.try_put(continue_msg()); 78 g.wait_for_all(); 79 printf( "after broadcast-push test, g_cnt == %d, b1==%d, b2==%d, b3==%d\n", (int)g_cnt, (int)b1, (int)b2, (int)b3); 80 } 81 82 83The output of this code is 84 85 86:: 87 88 89 after single-push test, g_cnt == 3, b1==3, b2==0, b3==0 90 after broadcast-push test, g_cnt == 9, b1==3, b2==3, b3==3 91 92 93The single-push test uses a ``buffer_node``, which has a "single-push" 94policy for forwarding messages. Putting three messages to the 95``buffer_node`` results in three messages being pushed. Notice also only 96the first ``function_node`` is sent to; in general there is no policy 97for which node is pushed to if more than one successor can accept. 98 99 100The broadcast-push test uses a ``broadcast_node``, which will push any 101message it receives to all accepting successors. Putting three messages 102to the ``broadcast_node`` results in a total of nine messages pushed to 103the ``function_nodes``. 104 105 106Only nodes designed to buffer (hold and forward received messages) have 107a "single-push" policy; all other nodes have a "broadcast-push" policy. 108 109Please see the :ref:`broadcast_or_send` section of 110:ref:`Flow_Graph_Tips`, and :ref:`Flow_Graph_Buffering_in_Nodes` for more 111information. 112 113