|
25 | 25 |
|
26 | 26 | #include "tbb/flow_graph.h" |
27 | 27 |
|
| 28 | +//! \file test_resource_limited_node.cpp |
| 29 | +//! \brief Test for [preview] functionality |
| 30 | + |
28 | 31 | using input_msg = conformance::message</*default_ctor = */true, /*copy_ctor = */true, /*copy_assign = */false>; |
29 | 32 | using output_msg = conformance::message</*default_ctor = */false, /*copy_ctor = */false, /*copy_assign = */false>; |
30 | 33 |
|
@@ -293,47 +296,78 @@ void test_root_genie() { |
293 | 296 | // TODO: add fairness checks |
294 | 297 | } |
295 | 298 |
|
296 | | -void test_cancellation_with_active_requests() { |
| 299 | +void test_cancellation_with_active_requests(bool exception) { |
297 | 300 | using namespace tbb::flow; |
298 | 301 |
|
299 | 302 | int resource_value = 1; |
300 | 303 | int input_value = 2; |
301 | 304 | resource_limiter<int> limiter(resource_value); |
302 | 305 |
|
303 | | - using node_type = resource_limited_node<int, std::tuple<int>>; |
| 306 | + using node_type = resource_limited_node<int, std::tuple<>>; |
304 | 307 | using ports_type = typename node_type::output_ports_type; |
| 308 | + |
| 309 | +#if TBB_USE_EXCEPTIONS |
| 310 | + struct body_exception {}; |
| 311 | +#endif |
| 312 | + |
| 313 | + tbb::task_group_context g2_context(tbb::task_group_context::isolated); |
| 314 | + graph g1; |
| 315 | + graph g2(g2_context); |
305 | 316 |
|
306 | | - graph g; |
| 317 | + const std::size_t n_submissions = 100; |
| 318 | + std::atomic<std::size_t> g2_node_body_counter{0}; |
307 | 319 |
|
308 | | - node_type cancel_node(g, unlimited, std::tie(limiter), |
309 | | - [&](int input, ports_type& ports, int resource) { |
| 320 | + node_type keep_using_node(g2, unlimited, std::tie(limiter), |
| 321 | + [&](int input, ports_type&, int resource) { |
310 | 322 | CHECK_MESSAGE(input == input_value, "Incorrect input"); |
311 | 323 | CHECK_MESSAGE(resource == resource_value, "Incorrect resource"); |
312 | 324 |
|
313 | | - for (int i = 0; i < 100; ++i) { |
314 | | - std::get<0>(ports).try_put(input); |
| 325 | + ++g2_node_body_counter; |
| 326 | + }); |
| 327 | + |
| 328 | + node_type cancel_node(g1, unlimited, std::tie(limiter), |
| 329 | + [&](int input, ports_type&, int resource) { |
| 330 | + CHECK_MESSAGE(input == input_value, "Incorrect input"); |
| 331 | + CHECK_MESSAGE(resource == resource_value, "Incorrect resource"); |
| 332 | + |
| 333 | + for (std::size_t i = 0; i < n_submissions; ++i) { |
| 334 | + keep_using_node.try_put(input); |
315 | 335 | } |
316 | 336 |
|
317 | | - g.cancel(); |
| 337 | + if (exception) { |
| 338 | +#if TBB_USE_EXCEPTIONS |
| 339 | + throw body_exception{}; |
| 340 | +#else |
| 341 | + CHECK_MESSAGE(false, "exception test was called when exceptions are not supported"); |
| 342 | +#endif |
| 343 | + } else { |
| 344 | + g1.cancel(); |
| 345 | + } |
318 | 346 |
|
319 | | - for (int i = 0; i < 100; ++i) { |
320 | | - std::get<0>(ports).try_put(input); |
| 347 | + for (std::size_t i = 0; i < n_submissions; ++i) { |
| 348 | + keep_using_node.try_put(input); |
321 | 349 | } |
322 | 350 | }); |
323 | 351 |
|
324 | | - std::atomic<std::size_t> num_bodies{0}; |
| 352 | + cancel_node.try_put(input_value); |
325 | 353 |
|
326 | | - node_type successor_node(g, unlimited, std::tie(limiter), |
327 | | - [&](int, ports_type&, int) { |
328 | | - ++num_bodies; |
329 | | - }); |
| 354 | +#if TBB_USE_EXCEPTIONS |
| 355 | + bool caught_exception = false; |
| 356 | + try { |
| 357 | + g1.wait_for_all(); |
| 358 | + } catch (body_exception) { |
| 359 | + caught_exception = true; |
| 360 | + } |
330 | 361 |
|
331 | | - make_edge(output_port<0>(cancel_node), successor_node); |
| 362 | + CHECK_MESSAGE(exception == caught_exception, "Expected exception was not caught"); |
| 363 | +#else |
| 364 | + g1.wait_for_all(); |
| 365 | +#endif |
332 | 366 |
|
333 | | - cancel_node.try_put(input_value); |
334 | | - g.wait_for_all(); |
335 | | - CHECK_MESSAGE(num_bodies < tbb::this_task_arena::max_concurrency(), |
336 | | - "Maximum number of node bodies exceeded"); |
| 367 | + g2.wait_for_all(); |
| 368 | + std::size_t expected_g2_body_calls = exception ? n_submissions : 2 * n_submissions; |
| 369 | + CHECK_MESSAGE(g2_node_body_counter == expected_g2_body_calls, |
| 370 | + "Incorrect number of g2 node body calls"); |
337 | 371 | } |
338 | 372 |
|
339 | 373 | //! \brief \ref interface |
@@ -463,6 +497,9 @@ TEST_CASE("resource_limited_node and std::invoke") { |
463 | 497 |
|
464 | 498 | //! \brief \ref error_guessing |
465 | 499 | TEST_CASE("resource_limited_node cancellation with active requests") { |
466 | | - test_cancellation_with_active_requests(); |
| 500 | + test_cancellation_with_active_requests(/*exception =*/false); |
| 501 | +#if TBB_USE_EXCEPTIONS |
| 502 | + test_cancellation_with_active_requests(/*exception = */true); |
| 503 | +#endif |
467 | 504 | } |
468 | 505 | #endif |
0 commit comments