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