From f6f72c871cd93e7f2673efea1c9cf353acc3106e Mon Sep 17 00:00:00 2001 From: HarunTeper Date: Mon, 9 Dec 2024 14:35:06 +0100 Subject: [PATCH 1/2] Added test for starvation in the multi-threaded executor Signed-off-by: HarunTeper --- .../test_multi_threaded_executor.cpp | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/rclcpp/test/rclcpp/executors/test_multi_threaded_executor.cpp b/rclcpp/test/rclcpp/executors/test_multi_threaded_executor.cpp index 09dfa03f90..32872482c4 100644 --- a/rclcpp/test/rclcpp/executors/test_multi_threaded_executor.cpp +++ b/rclcpp/test/rclcpp/executors/test_multi_threaded_executor.cpp @@ -102,3 +102,66 @@ TEST_F(TestMultiThreadedExecutor, timer_over_take) { executor.add_node(node); executor.spin(); } + +/* + Test that no tasks are starved + */ +TEST_F(TestMultiThreadedExecutor, starvation) { + rclcpp::executors::MultiThreadedExecutor executor(rclcpp::ExecutorOptions(), + 2u); + + std::shared_ptr node = + std::make_shared("test_multi_threaded_executor_starvation"); + + std::atomic_int timer_one_count{0}; + std::atomic_int timer_two_count{0}; + + rclcpp::TimerBase::SharedPtr timer_one; + rclcpp::TimerBase::SharedPtr timer_two; + + auto timer_one_callback = [&timer_one_count, &timer_two_count]() { + std::cout << "Timer one callback executed. Count: " + << timer_one_count.load() << std::endl; + + auto start_time = std::chrono::steady_clock::now(); + while (std::chrono::steady_clock::now() - start_time < 100ms) { + } + + timer_one_count++; + + auto diff = std::abs(timer_one_count - timer_two_count); + + std::cout << "Difference in counts: " << diff << std::endl; + + if (diff > 1) { + rclcpp::shutdown(); + ASSERT_LE(diff, 1); + } + }; + + auto timer_two_callback = [&timer_one_count, &timer_two_count]() { + std::cout << "Timer two callback executed. Count: " + << timer_two_count.load() << std::endl; + + auto start_time = std::chrono::steady_clock::now(); + while (std::chrono::steady_clock::now() - start_time < 100ms) { + } + + timer_two_count++; + + auto diff = std::abs(timer_one_count - timer_two_count); + + std::cout << "Difference in counts: " << diff << std::endl; + + if (diff > 1) { + rclcpp::shutdown(); + ASSERT_LE(diff, 1); + } + }; + + timer_one = node->create_wall_timer(0ms, timer_one_callback); + timer_two = node->create_wall_timer(0ms, timer_two_callback); + + executor.add_node(node); + executor.spin(); +} From af9b7c8f6a112f21cf1c6849231e7c4d75d65a95 Mon Sep 17 00:00:00 2001 From: HarunTeper Date: Mon, 6 Jan 2025 12:24:02 +0000 Subject: [PATCH 2/2] Refactor starvation test in multi-threaded executor to use sleep instead of busy wait Signed-off-by: HarunTeper --- .../test_multi_threaded_executor.cpp | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/rclcpp/test/rclcpp/executors/test_multi_threaded_executor.cpp b/rclcpp/test/rclcpp/executors/test_multi_threaded_executor.cpp index 32872482c4..59c9735458 100644 --- a/rclcpp/test/rclcpp/executors/test_multi_threaded_executor.cpp +++ b/rclcpp/test/rclcpp/executors/test_multi_threaded_executor.cpp @@ -120,12 +120,7 @@ TEST_F(TestMultiThreadedExecutor, starvation) { rclcpp::TimerBase::SharedPtr timer_two; auto timer_one_callback = [&timer_one_count, &timer_two_count]() { - std::cout << "Timer one callback executed. Count: " - << timer_one_count.load() << std::endl; - - auto start_time = std::chrono::steady_clock::now(); - while (std::chrono::steady_clock::now() - start_time < 100ms) { - } + std::this_thread::sleep_for(100ms); timer_one_count++; @@ -133,34 +128,27 @@ TEST_F(TestMultiThreadedExecutor, starvation) { std::cout << "Difference in counts: " << diff << std::endl; - if (diff > 1) { + if (timer_one_count > 10 || timer_two_count > 10) { rclcpp::shutdown(); ASSERT_LE(diff, 1); } }; auto timer_two_callback = [&timer_one_count, &timer_two_count]() { - std::cout << "Timer two callback executed. Count: " - << timer_two_count.load() << std::endl; - - auto start_time = std::chrono::steady_clock::now(); - while (std::chrono::steady_clock::now() - start_time < 100ms) { - } + std::this_thread::sleep_for(100ms); timer_two_count++; auto diff = std::abs(timer_one_count - timer_two_count); - std::cout << "Difference in counts: " << diff << std::endl; - - if (diff > 1) { + if (timer_one_count > 10 || timer_two_count > 10) { rclcpp::shutdown(); ASSERT_LE(diff, 1); } }; - timer_one = node->create_wall_timer(0ms, timer_one_callback); - timer_two = node->create_wall_timer(0ms, timer_two_callback); + timer_one = node->create_wall_timer(10ms, timer_one_callback); + timer_two = node->create_wall_timer(10ms, timer_two_callback); executor.add_node(node); executor.spin();