@@ -242,42 +242,30 @@ class Executor
242242 * spin_node_once to block indefinitely (the default behavior). A timeout of 0 causes this
243243 * function to be non-blocking.
244244 */
245- template < typename RepT = int64_t , typename T = std::milli>
246- void
245+ RCLCPP_PUBLIC
246+ virtual void
247247 spin_node_once (
248- rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node,
249- std::chrono::duration<RepT, T> timeout = std::chrono::duration<RepT, T>(-1 ))
250- {
251- return spin_node_once_nanoseconds (
252- node,
253- std::chrono::duration_cast<std::chrono::nanoseconds>(timeout)
254- );
255- }
248+ const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node,
249+ std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1 ));
256250
257251 // / Convenience function which takes Node and forwards NodeBaseInterface.
258- template < typename NodeT = rclcpp::Node, typename RepT = int64_t , typename T = std::milli>
259- void
252+ RCLCPP_PUBLIC
253+ virtual void
260254 spin_node_once (
261- std::shared_ptr<NodeT> node,
262- std::chrono::duration<RepT, T> timeout = std::chrono::duration<RepT, T>(-1 ))
263- {
264- return spin_node_once_nanoseconds (
265- node->get_node_base_interface (),
266- std::chrono::duration_cast<std::chrono::nanoseconds>(timeout)
267- );
268- }
255+ const std::shared_ptr<rclcpp::Node> & node,
256+ std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1 ));
269257
270258 // / Add a node, complete all immediately available work, and remove the node.
271259 /* *
272260 * \param[in] node Shared pointer to the node to add.
273261 */
274262 RCLCPP_PUBLIC
275- void
263+ virtual void
276264 spin_node_some (rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node);
277265
278266 // / Convenience function which takes Node and forwards NodeBaseInterface.
279267 RCLCPP_PUBLIC
280- void
268+ virtual void
281269 spin_node_some (std::shared_ptr<rclcpp::Node> node);
282270
283271 // / Collect work once and execute all available work, optionally within a max duration.
@@ -307,14 +295,14 @@ class Executor
307295 * \param[in] node Shared pointer to the node to add.
308296 */
309297 RCLCPP_PUBLIC
310- void
298+ virtual void
311299 spin_node_all (
312300 rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node,
313301 std::chrono::nanoseconds max_duration);
314302
315303 // / Convenience function which takes Node and forwards NodeBaseInterface.
316304 RCLCPP_PUBLIC
317- void
305+ virtual void
318306 spin_node_all (std::shared_ptr<rclcpp::Node> node, std::chrono::nanoseconds max_duration);
319307
320308 // / Collect and execute work repeatedly within a duration or until no more work is available.
@@ -366,52 +354,11 @@ class Executor
366354 const FutureT & future,
367355 std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1 ))
368356 {
369- // TODO(wjwwood): does not work recursively; can't call spin_node_until_future_complete
370- // inside a callback executed by an executor.
371-
372- // Check the future before entering the while loop.
373- // If the future is already complete, don't try to spin.
374- std::future_status status = future.wait_for (std::chrono::seconds (0 ));
375- if (status == std::future_status::ready) {
376- return FutureReturnCode::SUCCESS;
377- }
378-
379- auto end_time = std::chrono::steady_clock::now ();
380- std::chrono::nanoseconds timeout_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
381- timeout);
382- if (timeout_ns > std::chrono::nanoseconds::zero ()) {
383- end_time += timeout_ns;
384- }
385- std::chrono::nanoseconds timeout_left = timeout_ns;
386-
387- if (spinning.exchange (true )) {
388- throw std::runtime_error (" spin_until_future_complete() called while already spinning" );
357+ return spin_until_future_complete_impl (std::chrono::duration_cast<std::chrono::nanoseconds>(
358+ timeout), [&future] () {
359+ return future.wait_for (std::chrono::seconds (0 ));
389360 }
390- RCPPUTILS_SCOPE_EXIT (this ->spinning .store (false ); );
391- while (rclcpp::ok (this ->context_ ) && spinning.load ()) {
392- // Do one item of work.
393- spin_once_impl (timeout_left);
394-
395- // Check if the future is set, return SUCCESS if it is.
396- status = future.wait_for (std::chrono::seconds (0 ));
397- if (status == std::future_status::ready) {
398- return FutureReturnCode::SUCCESS;
399- }
400- // If the original timeout is < 0, then this is blocking, never TIMEOUT.
401- if (timeout_ns < std::chrono::nanoseconds::zero ()) {
402- continue ;
403- }
404- // Otherwise check if we still have time to wait, return TIMEOUT if not.
405- auto now = std::chrono::steady_clock::now ();
406- if (now >= end_time) {
407- return FutureReturnCode::TIMEOUT;
408- }
409- // Subtract the elapsed time from the original timeout.
410- timeout_left = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - now);
411- }
412-
413- // The future did not complete before ok() returned false, return INTERRUPTED.
414- return FutureReturnCode::INTERRUPTED;
361+ );
415362 }
416363
417364 // / Cancel any running spin* function, causing it to return.
@@ -420,7 +367,7 @@ class Executor
420367 * \throws std::runtime_error if there is an issue triggering the guard condition
421368 */
422369 RCLCPP_PUBLIC
423- void
370+ virtual void
424371 cancel ();
425372
426373 // / Returns true if the executor is currently spinning.
@@ -429,10 +376,19 @@ class Executor
429376 * \return True if the executor is currently spinning.
430377 */
431378 RCLCPP_PUBLIC
432- bool
379+ virtual bool
433380 is_spinning ();
434381
435382protected:
383+ // constructor that will not setup any internals.
384+ /* *
385+ * This constructor is intended to be used by any derived executor,
386+ * that explicitly does not want to use the default implementation provided
387+ * by this class. This constructor is guaranteed, to not modify the system
388+ * state.
389+ * */
390+ explicit Executor (const std::shared_ptr<rclcpp::Context> & context);
391+
436392 // / Add a node to executor, execute the next available unit of work, and remove the node.
437393 /* *
438394 * Implementation of spin_node_once using std::chrono::nanoseconds
@@ -447,6 +403,10 @@ class Executor
447403 rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node,
448404 std::chrono::nanoseconds timeout);
449405
406+ virtual FutureReturnCode spin_until_future_complete_impl (
407+ std::chrono::nanoseconds max_duration,
408+ const std::function<std::future_status ()> & get_future_status);
409+
450410 // / Collect work and execute available work, optionally within a duration.
451411 /* *
452412 * Implementation of spin_some and spin_all.
0 commit comments