1.. _avoiding_data_races: 2 3Avoiding Data Races 4=================== 5 6 7The edges in a flow graph make explicit the dependence relationships 8that you want the library to enforce. Similarly, the concurrency limits 9on ``function_node`` and ``multifunction_node`` objects limit the maximum number 10of concurrent invocations that the runtime library will allow. These are 11the limits that are enforced by the library; the library does not 12automatically protect you from data races. You must explicitly prevent 13data races by using these mechanisms. 14 15 16For example, the follow code has a data race because there is nothing to 17prevent concurrent accesses to the global count object referenced by 18node f: 19 20 21:: 22 23 24 graph g; 25 int src_count = 1; 26 int global_sum = 0; 27 int limit = 100000; 28 29 input_node< int > src( g, [&]( oneapi::tbb::flow_control& fc ) -> int { 30 if ( src_count <= limit ) { 31 return src_count++; 32 } else { 33 fc.stop(); 34 return int(); 35 } 36 } ); 37 src.activate(); 38 39 function_node< int, int > f( g, unlimited, [&]( int i ) -> int { 40 global_sum += i; // data race on global_sum 41 return i; 42 } ); 43 44 45 make_edge( src, f ); 46 g.wait_for_all(); 47 48 49 cout << "global sum = " << global_sum 50 << " and closed form = " << limit*(limit+1)/2 << "\n"; 51 52 53If you run the above example, it will likely calculate a global sum that 54is a bit smaller than the expected solution due to the data race. The 55data race could be avoided in this simple example by changing the 56allowed concurrency in ``f`` from unlimited to 1, forcing each value to be 57processed sequentially by ``f``. You may also note that the ``input_node`` also 58updates a global value, ``src_count``. However, since an ``input_node`` always 59executes serially, there is no race possible. 60