From eb36918c3c85c850ca917294a7a08fc552993803 Mon Sep 17 00:00:00 2001 From: Alejandro Hernandez Cordero Date: Thu, 1 May 2025 11:09:56 +0200 Subject: [PATCH] Removed deprecated StaticSingleThreadedExecutor Signed-off-by: Alejandro Hernandez Cordero --- rclcpp/CMakeLists.txt | 1 - rclcpp/include/rclcpp/executors.hpp | 1 - .../static_single_threaded_executor.hpp | 145 ------------ .../static_single_threaded_executor.cpp | 223 ------------------ rclcpp/test/rclcpp/CMakeLists.txt | 7 - .../test/rclcpp/executors/executor_types.hpp | 37 --- .../test_executors_timer_cancel_behavior.cpp | 13 +- .../test_static_single_threaded_executor.cpp | 192 --------------- 8 files changed, 2 insertions(+), 617 deletions(-) delete mode 100644 rclcpp/include/rclcpp/executors/static_single_threaded_executor.hpp delete mode 100644 rclcpp/src/rclcpp/executors/static_single_threaded_executor.cpp delete mode 100644 rclcpp/test/rclcpp/executors/test_static_single_threaded_executor.cpp diff --git a/rclcpp/CMakeLists.txt b/rclcpp/CMakeLists.txt index 8712b48856..aba6ab0b19 100644 --- a/rclcpp/CMakeLists.txt +++ b/rclcpp/CMakeLists.txt @@ -70,7 +70,6 @@ set(${PROJECT_NAME}_SRCS src/rclcpp/executors/executor_notify_waitable.cpp src/rclcpp/executors/multi_threaded_executor.cpp src/rclcpp/executors/single_threaded_executor.cpp - src/rclcpp/executors/static_single_threaded_executor.cpp src/rclcpp/expand_topic_or_service_name.cpp src/rclcpp/experimental/executors/events_executor/events_executor.cpp src/rclcpp/experimental/timers_manager.cpp diff --git a/rclcpp/include/rclcpp/executors.hpp b/rclcpp/include/rclcpp/executors.hpp index adb9c6d6c6..1cd4d8666b 100644 --- a/rclcpp/include/rclcpp/executors.hpp +++ b/rclcpp/include/rclcpp/executors.hpp @@ -20,7 +20,6 @@ #include "rclcpp/executors/multi_threaded_executor.hpp" #include "rclcpp/executors/single_threaded_executor.hpp" -#include "rclcpp/executors/static_single_threaded_executor.hpp" #include "rclcpp/experimental/executors/events_executor/events_executor.hpp" #include "rclcpp/node.hpp" #include "rclcpp/utilities.hpp" diff --git a/rclcpp/include/rclcpp/executors/static_single_threaded_executor.hpp b/rclcpp/include/rclcpp/executors/static_single_threaded_executor.hpp deleted file mode 100644 index 33674465a8..0000000000 --- a/rclcpp/include/rclcpp/executors/static_single_threaded_executor.hpp +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2019 Nobleo Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef RCLCPP__EXECUTORS__STATIC_SINGLE_THREADED_EXECUTOR_HPP_ -#define RCLCPP__EXECUTORS__STATIC_SINGLE_THREADED_EXECUTOR_HPP_ - -#include -#include -#include - -#include "rclcpp/executor.hpp" -#include "rclcpp/executors/executor_entities_collection.hpp" -#include "rclcpp/executors/single_threaded_executor.hpp" - -namespace rclcpp -{ -namespace executors -{ - -/// Static executor implementation -/** - * This executor is a static version of the original single threaded executor. - * It contains some performance optimization to avoid unnecessary reconstructions of - * the executable list for every iteration. - * All nodes, callbackgroups, timers, subscriptions etc. are created before - * spin() is called, and modified only when an entity is added/removed to/from a node. - * This executor is deprecated because these performance improvements have now been - * applied to all other executors. - * This executor is also considered unstable due to known bugs. - * See the unit-tests that are only applied to `StandardExecutors` for information - * on the known limitations. - * - * To run this executor instead of SingleThreadedExecutor replace: - * rclcpp::executors::SingleThreadedExecutor exec; - * by - * rclcpp::executors::StaticSingleThreadedExecutor exec; - * in your source code and spin node(s) in the following way: - * exec.add_node(node); - * exec.spin(); - * exec.remove_node(node); - */ -class [[deprecated("Use rclcpp::executors::SingleThreadedExecutor")]] StaticSingleThreadedExecutor - : public rclcpp::Executor -{ -public: - RCLCPP_SMART_PTR_DEFINITIONS(StaticSingleThreadedExecutor) - - /// Default constructor. See the default constructor for Executor. - RCLCPP_PUBLIC - explicit StaticSingleThreadedExecutor( - const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions()); - - /// Default destructor. - RCLCPP_PUBLIC - virtual ~StaticSingleThreadedExecutor(); - - /// Static executor implementation of spin. - /** - * This function will block until work comes in, execute it, and keep blocking. - * It will only be interrupted by a CTRL-C (managed by the global signal handler). - * \throws std::runtime_error when spin() called while already spinning - */ - RCLCPP_PUBLIC - void - spin() override; - - /// Static executor implementation of spin some - /** - * This non-blocking function will execute entities that - * were ready when this API was called, until timeout or no - * more work available. Entities that got ready while - * executing work, won't be taken into account here. - * - * Example: - * while(condition) { - * spin_some(); - * sleep(); // User should have some sync work or - * // sleep to avoid a 100% CPU usage - * } - */ - RCLCPP_PUBLIC - void - spin_some(std::chrono::nanoseconds max_duration = std::chrono::nanoseconds(0)) override; - - /// Static executor implementation of spin all - /** - * This non-blocking function will execute entities until timeout (must be >= 0) - * or no more work available. - * If timeout is `0`, potentially it blocks forever until no more work is available. - * If new entities get ready while executing work available, they will be executed - * as long as the timeout hasn't expired. - * - * Example: - * while(condition) { - * spin_all(); - * sleep(); // User should have some sync work or - * // sleep to avoid a 100% CPU usage - * } - */ - RCLCPP_PUBLIC - void - spin_all(std::chrono::nanoseconds max_duration) override; - -protected: - /** - * @brief Executes ready executables from wait set. - * @param collection entities to evaluate for ready executables. - * @param wait_result result to check for ready executables. - * @param spin_once if true executes only the first ready executable. - * @return true if any executable was ready. - */ - bool - execute_ready_executables( - const rclcpp::executors::ExecutorEntitiesCollection & collection, - rclcpp::WaitResult & wait_result, - bool spin_once); - - void - spin_some_impl(std::chrono::nanoseconds max_duration, bool exhaustive); - - void - spin_once_impl(std::chrono::nanoseconds timeout) override; - - std::optional> - collect_and_wait(std::chrono::nanoseconds timeout); - -private: - RCLCPP_DISABLE_COPY(StaticSingleThreadedExecutor) -}; - -} // namespace executors -} // namespace rclcpp - -#endif // RCLCPP__EXECUTORS__STATIC_SINGLE_THREADED_EXECUTOR_HPP_ diff --git a/rclcpp/src/rclcpp/executors/static_single_threaded_executor.cpp b/rclcpp/src/rclcpp/executors/static_single_threaded_executor.cpp deleted file mode 100644 index b16526899a..0000000000 --- a/rclcpp/src/rclcpp/executors/static_single_threaded_executor.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright 2019 Nobleo Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "rclcpp/executors/executor_entities_collection.hpp" -#include "rcpputils/scope_exit.hpp" - -#include "rclcpp/executors/static_single_threaded_executor.hpp" -#include "rclcpp/any_executable.hpp" - -using rclcpp::executors::StaticSingleThreadedExecutor; - -StaticSingleThreadedExecutor::StaticSingleThreadedExecutor(const rclcpp::ExecutorOptions & options) -: rclcpp::Executor(options) -{ -} - -StaticSingleThreadedExecutor::~StaticSingleThreadedExecutor() {} - -void -StaticSingleThreadedExecutor::spin() -{ - if (spinning.exchange(true)) { - throw std::runtime_error("spin() called while already spinning"); - } - RCPPUTILS_SCOPE_EXIT(this->spinning.store(false); ); - - // This is essentially the contents of the rclcpp::Executor::wait_for_work method, - // except we need to keep the wait result to reproduce the StaticSingleThreadedExecutor - // behavior. - while (rclcpp::ok(this->context_) && spinning.load()) { - this->spin_once_impl(std::chrono::nanoseconds(-1)); - } -} - -void -StaticSingleThreadedExecutor::spin_some(std::chrono::nanoseconds max_duration) -{ - // In this context a 0 input max_duration means no duration limit - if (std::chrono::nanoseconds(0) == max_duration) { - max_duration = std::chrono::nanoseconds::max(); - } - return this->spin_some_impl(max_duration, false); -} - -void -StaticSingleThreadedExecutor::spin_all(std::chrono::nanoseconds max_duration) -{ - if (max_duration < std::chrono::nanoseconds(0)) { - throw std::invalid_argument("max_duration must be greater than or equal to 0"); - } - return this->spin_some_impl(max_duration, true); -} - -void -StaticSingleThreadedExecutor::spin_some_impl(std::chrono::nanoseconds max_duration, bool exhaustive) -{ - auto start = std::chrono::steady_clock::now(); - auto max_duration_not_elapsed = [max_duration, start]() { - const auto spin_forever = std::chrono::nanoseconds(0) == max_duration; - const auto cur_duration = std::chrono::steady_clock::now() - start; - return spin_forever || (cur_duration < max_duration); - }; - - if (spinning.exchange(true)) { - throw std::runtime_error("spin_some() called while already spinning"); - } - RCPPUTILS_SCOPE_EXIT(this->spinning.store(false);); - - while (rclcpp::ok(context_) && spinning.load() && max_duration_not_elapsed()) { - // Get executables that are ready now - std::lock_guard guard(mutex_); - - auto wait_result = this->collect_and_wait(std::chrono::nanoseconds(0)); - if (wait_result.has_value()) { - // Execute ready executables - bool work_available = this->execute_ready_executables( - current_collection_, - wait_result.value(), - false); - if (!work_available || !exhaustive) { - break; - } - } - } -} - -void -StaticSingleThreadedExecutor::spin_once_impl(std::chrono::nanoseconds timeout) -{ - if (rclcpp::ok(context_) && spinning.load()) { - std::lock_guard guard(mutex_); - auto wait_result = this->collect_and_wait(timeout); - if (wait_result.has_value()) { - this->execute_ready_executables(current_collection_, wait_result.value(), true); - } - } -} - -std::optional> -StaticSingleThreadedExecutor::collect_and_wait(std::chrono::nanoseconds timeout) -{ - // we need to make sure that callback groups don't get out of scope - // during the wait. As in jazzy, they are not covered by the DynamicStorage, - // we explicitly hold them here as a bugfix - std::vector cbgs; - - if (this->entities_need_rebuild_.exchange(false) || current_collection_.empty()) { - this->collect_entities(); - } - - auto callback_groups = this->collector_.get_all_callback_groups(); - cbgs.resize(callback_groups.size()); - for(const auto & w_ptr : callback_groups) { - auto shr_ptr = w_ptr.lock(); - if(shr_ptr) { - cbgs.push_back(std::move(shr_ptr)); - } - } - - auto wait_result = wait_set_.wait(std::chrono::nanoseconds(timeout)); - - // drop references to the callback groups, before trying to execute anything - cbgs.clear(); - - if (wait_result.kind() == WaitResultKind::Empty) { - RCUTILS_LOG_WARN_NAMED( - "rclcpp", - "empty wait set received in wait(). This should never happen."); - return {}; - } else { - if (wait_result.kind() == WaitResultKind::Ready && current_notify_waitable_) { - auto & rcl_wait_set = wait_result.get_wait_set().get_rcl_wait_set(); - if (current_notify_waitable_->is_ready(rcl_wait_set)) { - current_notify_waitable_->execute(current_notify_waitable_->take_data()); - } - } - } - return wait_result; -} - -// This preserves the "scheduling semantics" of the StaticSingleThreadedExecutor -// from the original implementation. -bool StaticSingleThreadedExecutor::execute_ready_executables( - const rclcpp::executors::ExecutorEntitiesCollection & collection, - rclcpp::WaitResult & wait_result, - bool spin_once) -{ - bool any_ready_executable = false; - if (wait_result.kind() != rclcpp::WaitResultKind::Ready) { - return any_ready_executable; - } - - while (auto subscription = wait_result.next_ready_subscription()) { - auto entity_iter = collection.subscriptions.find(subscription->get_subscription_handle().get()); - if (entity_iter != collection.subscriptions.end()) { - execute_subscription(subscription); - any_ready_executable = true; - if (spin_once) {return any_ready_executable;} - } - } - - size_t current_timer_index = 0; - while (true) { - auto [timer, timer_index] = wait_result.peek_next_ready_timer(current_timer_index); - if (nullptr == timer) { - break; - } - current_timer_index = timer_index; - auto entity_iter = collection.timers.find(timer->get_timer_handle().get()); - if (entity_iter != collection.timers.end()) { - wait_result.clear_timer_with_index(current_timer_index); - auto data = timer->call(); - if (!data) { - // someone canceled the timer between is_ready and call - continue; - } - - execute_timer(std::move(timer), data); - any_ready_executable = true; - if (spin_once) {return any_ready_executable;} - } - } - - while (auto client = wait_result.next_ready_client()) { - auto entity_iter = collection.clients.find(client->get_client_handle().get()); - if (entity_iter != collection.clients.end()) { - execute_client(client); - any_ready_executable = true; - if (spin_once) {return any_ready_executable;} - } - } - - while (auto service = wait_result.next_ready_service()) { - auto entity_iter = collection.services.find(service->get_service_handle().get()); - if (entity_iter != collection.services.end()) { - execute_service(service); - any_ready_executable = true; - if (spin_once) {return any_ready_executable;} - } - } - - while (auto waitable = wait_result.next_ready_waitable()) { - auto entity_iter = collection.waitables.find(waitable.get()); - if (entity_iter != collection.waitables.end()) { - const auto data = waitable->take_data(); - waitable->execute(data); - any_ready_executable = true; - if (spin_once) {return any_ready_executable;} - } - } - return any_ready_executable; -} diff --git a/rclcpp/test/rclcpp/CMakeLists.txt b/rclcpp/test/rclcpp/CMakeLists.txt index 3ae3fa7306..eb85b1385a 100644 --- a/rclcpp/test/rclcpp/CMakeLists.txt +++ b/rclcpp/test/rclcpp/CMakeLists.txt @@ -534,13 +534,6 @@ if(TARGET test_executors_warmup) target_link_libraries(test_executors_warmup ${PROJECT_NAME} ${test_msgs_TARGETS}) endif() -ament_add_gtest(test_static_single_threaded_executor executors/test_static_single_threaded_executor.cpp - APPEND_LIBRARY_DIRS "${append_library_dirs}") -ament_add_test_label(test_static_single_threaded_executor mimick) -if(TARGET test_static_single_threaded_executor) - target_link_libraries(test_static_single_threaded_executor ${PROJECT_NAME} mimick ${test_msgs_TARGETS}) -endif() - ament_add_gtest(test_multi_threaded_executor executors/test_multi_threaded_executor.cpp APPEND_LIBRARY_DIRS "${append_library_dirs}") if(TARGET test_multi_threaded_executor) diff --git a/rclcpp/test/rclcpp/executors/executor_types.hpp b/rclcpp/test/rclcpp/executors/executor_types.hpp index 0478eb0e25..893b88ff66 100644 --- a/rclcpp/test/rclcpp/executors/executor_types.hpp +++ b/rclcpp/test/rclcpp/executors/executor_types.hpp @@ -22,40 +22,13 @@ #include "rclcpp/experimental/executors/events_executor/events_executor.hpp" #include "rclcpp/executors/single_threaded_executor.hpp" -#include "rclcpp/executors/static_single_threaded_executor.hpp" #include "rclcpp/executors/multi_threaded_executor.hpp" -// suppress deprecated StaticSingleThreadedExecutor warning -// we define an alias that explicitly indicates that this class is deprecated, while avoiding -// polluting a lot of files the gcc pragmas -#if !defined(_WIN32) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#else // !defined(_WIN32) -# pragma warning(push) -# pragma warning(disable: 4996) -#endif -using DeprecatedStaticSingleThreadedExecutor = rclcpp::executors::StaticSingleThreadedExecutor; -// remove warning suppression -#if !defined(_WIN32) -# pragma GCC diagnostic pop -#else // !defined(_WIN32) -# pragma warning(pop) -#endif - -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" -#endif using ExecutorTypes = ::testing::Types< rclcpp::executors::SingleThreadedExecutor, rclcpp::executors::MultiThreadedExecutor, - DeprecatedStaticSingleThreadedExecutor, rclcpp::experimental::executors::EventsExecutor>; -#ifdef __clang__ -# pragma clang diagnostic pop -#endif class ExecutorTypeNames { @@ -70,16 +43,6 @@ class ExecutorTypeNames if (std::is_same()) { return "MultiThreadedExecutor"; } -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" -#endif - if (std::is_same()) { - return "StaticSingleThreadedExecutor"; - } -#ifdef __clang__ -# pragma clang diagnostic pop -#endif if (std::is_same()) { return "EventsExecutor"; diff --git a/rclcpp/test/rclcpp/executors/test_executors_timer_cancel_behavior.cpp b/rclcpp/test/rclcpp/executors/test_executors_timer_cancel_behavior.cpp index ea1007a779..4dfe6e612d 100644 --- a/rclcpp/test/rclcpp/executors/test_executors_timer_cancel_behavior.cpp +++ b/rclcpp/test/rclcpp/executors/test_executors_timer_cancel_behavior.cpp @@ -285,20 +285,11 @@ class TestTimerCancelBehavior : public ::testing::Test T executor; }; -#if !defined(_WIN32) -# ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" -# endif -#endif using MainExecutorTypes = ::testing::Types< rclcpp::executors::SingleThreadedExecutor, - rclcpp::executors::MultiThreadedExecutor, - DeprecatedStaticSingleThreadedExecutor>; -#ifdef __clang__ -# pragma clang diagnostic pop -#endif + rclcpp::executors::MultiThreadedExecutor>; + // TODO(@fujitatomoya): this test excludes EventExecutor because it does not // support simulation time used for this test to relax the racy condition. // See more details for https://github.com/ros2/rclcpp/issues/2457. diff --git a/rclcpp/test/rclcpp/executors/test_static_single_threaded_executor.cpp b/rclcpp/test/rclcpp/executors/test_static_single_threaded_executor.cpp deleted file mode 100644 index 8e330cbebc..0000000000 --- a/rclcpp/test/rclcpp/executors/test_static_single_threaded_executor.cpp +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2020 Open Source Robotics Foundation, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include - -#include -#include -#include -#include - -#include "rclcpp/exceptions.hpp" -#include "rclcpp/executors.hpp" -#include "rclcpp/node.hpp" -#include "rclcpp/rclcpp.hpp" - -#include "test_msgs/srv/empty.hpp" - -#include "./executor_types.hpp" -#include "../../mocking_utils/patch.hpp" -#include "../../utils/rclcpp_gtest_macros.hpp" - -using namespace std::chrono_literals; - -class TestStaticSingleThreadedExecutor : public ::testing::Test -{ -public: - void SetUp() - { - rclcpp::init(0, nullptr); - } - - void TearDown() - { - rclcpp::shutdown(); - } -}; - -TEST_F(TestStaticSingleThreadedExecutor, add_callback_group_trigger_guard_failed) { -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" -#endif - - DeprecatedStaticSingleThreadedExecutor executor; -#ifdef __clang__ -# pragma clang diagnostic pop -#endif - auto node = std::make_shared("node", "ns"); - rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group( - rclcpp::CallbackGroupType::MutuallyExclusive); - - { - auto mock = mocking_utils::patch_and_return( - "lib:rclcpp", rcl_trigger_guard_condition, RCL_RET_ERROR); - RCLCPP_EXPECT_THROW_EQ( - executor.add_callback_group(cb_group, node->get_node_base_interface(), true), - std::runtime_error("Failed to handle entities update on callback group add: error not set")); - } -} - -TEST_F(TestStaticSingleThreadedExecutor, add_node_trigger_guard_failed) { -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" -#endif - - DeprecatedStaticSingleThreadedExecutor executor; -#ifdef __clang__ -# pragma clang diagnostic pop -#endif - auto node = std::make_shared("node", "ns"); - - { - auto mock = mocking_utils::patch_and_return( - "lib:rclcpp", rcl_trigger_guard_condition, RCL_RET_ERROR); - RCLCPP_EXPECT_THROW_EQ( - executor.add_node(node), - std::runtime_error("Failed to handle entities update on node add: error not set")); - } -} - -TEST_F(TestStaticSingleThreadedExecutor, remove_callback_group_trigger_guard_failed) { -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" -#endif - - DeprecatedStaticSingleThreadedExecutor executor; -#ifdef __clang__ -# pragma clang diagnostic pop -#endif - auto node = std::make_shared("node", "ns"); - rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group( - rclcpp::CallbackGroupType::MutuallyExclusive); - - executor.add_callback_group(cb_group, node->get_node_base_interface(), true); - - { - auto mock = mocking_utils::patch_and_return( - "lib:rclcpp", rcl_trigger_guard_condition, RCL_RET_ERROR); - RCLCPP_EXPECT_THROW_EQ( - executor.remove_callback_group(cb_group, true), - std::runtime_error( - "Failed to handle entities update on callback group remove: error not set")); - } -} - -TEST_F(TestStaticSingleThreadedExecutor, remove_node_failed) { -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" -#endif - - DeprecatedStaticSingleThreadedExecutor executor; -#ifdef __clang__ -# pragma clang diagnostic pop -#endif - auto node = std::make_shared("node", "ns"); - - { - auto mock = mocking_utils::patch_and_return( - "lib:rclcpp", rcl_trigger_guard_condition, RCL_RET_ERROR); - RCLCPP_EXPECT_THROW_EQ( - executor.remove_node(node, true), - std::runtime_error("Node '/ns/node' needs to be associated with an executor.")); - } -} - -TEST_F(TestStaticSingleThreadedExecutor, remove_node_trigger_guard_failed) { -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" -#endif - - DeprecatedStaticSingleThreadedExecutor executor; -#ifdef __clang__ -# pragma clang diagnostic pop -#endif - auto node = std::make_shared("node", "ns"); - - executor.add_node(node); - - { - auto mock = mocking_utils::patch_and_return( - "lib:rclcpp", rcl_trigger_guard_condition, RCL_RET_ERROR); - RCLCPP_EXPECT_THROW_EQ( - executor.remove_node(node, true), - std::runtime_error("Failed to handle entities update on node remove: error not set")); - } -} - -TEST_F(TestStaticSingleThreadedExecutor, execute_service) { -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" -#endif - - DeprecatedStaticSingleThreadedExecutor executor; -#ifdef __clang__ -# pragma clang diagnostic pop -#endif - auto node = std::make_shared("node", "ns"); - executor.add_node(node); - - auto service = - node->create_service( - "service", - []( - const test_msgs::srv::Empty::Request::SharedPtr, - test_msgs::srv::Empty::Response::SharedPtr) {}); - auto client = node->create_client("service"); - - std::promise promise; - std::future future = promise.get_future(); - EXPECT_EQ( - rclcpp::FutureReturnCode::TIMEOUT, - executor.spin_until_future_complete(future, std::chrono::milliseconds(1))); - - executor.remove_node(node); - executor.spin_until_future_complete(future, std::chrono::milliseconds(1)); -}