Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add wait_for_service() and service_is_ready() to Client #222

Merged
merged 17 commits into from
Jun 23, 2016

Conversation

wjwwood
Copy link
Member

@wjwwood wjwwood commented May 27, 2016

Replacement for #221

Connects to ros2/ros2#215

@wjwwood wjwwood added the in progress Actively being worked on (Kanban column) label May 27, 2016
@wjwwood wjwwood force-pushed the wait_for_service2 branch 2 times, most recently from 642174d to 7f74cb9 Compare June 9, 2016 01:51
@wjwwood wjwwood changed the title initial implementation of wait_for_service, WIP initial implementation of wait_for_service Jun 9, 2016
@wjwwood wjwwood changed the title initial implementation of wait_for_service add wait_for_service() and service_is_ready() to Client Jun 9, 2016
@wjwwood wjwwood force-pushed the wait_for_service2 branch 2 times, most recently from 9a3afec to 760efde Compare June 9, 2016 21:29
} // release the nodes_ lock

// Wait for graph changes or interrupt.
ret = rcl_wait(&wait_set_, -1); // block for ever until one of the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete comment here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wjwwood wjwwood self-assigned this Jun 15, 2016
@wjwwood wjwwood added in review Waiting for review (Kanban column) and removed in progress Actively being worked on (Kanban column) labels Jun 15, 2016
@wjwwood
Copy link
Member Author

wjwwood commented Jun 15, 2016

This needs review. @jacquelinekay already reviewed in some while helping me find and fix a bug.

A few things I want to highlight and to "request comments" about:

  • Exceptions:
    • I have been trying in this pull request to be better about throwing specific exceptions.
    • However, I'm not sure how granular to make them, so I'm open to suggestion on how to adjust those.
    • Also, I'm not sure how best to organize the exceptions: all in one header (rclcpp/exceptions.hpp) or all in the files they're related to (Node specific exceptions in rclcpp/node.hpp) or a mixture of both?
      • Currently I have a mixture of both, with some generic RCL exceptions and help functions in the rclcpp/exceptions.hpp header, and other exceptions in node.hpp and graph_listener.hpp.
  • GraphListener:
    • The design is such that there is a single GraphListener with a single thread for all nodes in the given context.
    • This allows us to wait on all graph changes from all nodes in a single thread.
    • Waiting on graph changes in a thread allows functions like wait_for_service to work without an executor spinning.
    • It is setup to only create the thread and wake-up in that thread if there are nodes which need to be notified of graph changes, so it's lazy in that way to conserve resources when not being used.
  • Testing:
    • All the new code is tested via integration tests in test_communication, test_rclcpp, and rclcpp_examples.
    • I wanted to test GraphListener in a unit test fashion, but I found it too difficult to do so since it takes a full Node into most of its arguments.
      • Mocking Node to simplify the GraphListener tests is too hard, or impossible without dirty hacks, see: https://github.com/ros2/rclcpp/blob/master/rclcpp/test/test_intra_process_manager.cpp#L23-L133
      • I have a plan on how to change the headers in rclcpp to make this easier, but I think that's out of scope for this pull request. However, adding narrower tests for these classes would hopefully be easier after the changes. I wanted to discuss them at the last meeting but we ran out of time.

I think that's all I wanted to highlight. Thanks in advance for reviews.

}
// server is not ready, loop if there is time left
time_to_wait = timeout - (std::chrono::steady_clock::now() - start);
} while (timeout < std::chrono::nanoseconds(0) || time_to_wait > std::chrono::nanoseconds(0));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens in this loop when the program receives SIGINT/CTRL-C?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question... Currently I think it will not wake up, because neither node_->wait_for_graph_change nor this loop will consider rclcpp::ok or be notified by the shutdown call or signal processor.

What do you think the behavior of this function should be in that case? I'll need to adjust the documentation to be something like "returns true if graph changed or false if the timeout expired or rclcpp::shutdown occurred". But then you can't easily tell which happened timeout or shutdown, though I guess if you check rclcpp::ok after getting false back from this function and be reasonably sure that was the cause or not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine to check for !rclcpp::ok() in the while predicate and return false in that case. A return value of false means "we stopped waiting and the client was not ready." If you want a finer level of granularity we could add error codes (client_ready, timeout, interrupted) but I don't think that's necessary right now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I added this behavior in 25e17b0 and I added a test in ros2/system_tests@268f54a.

@jacquelinekay
Copy link
Contributor

My major questions are about what happens in the do/while loop on CTRL-C, and the ownership of the Node pointer in Client. Otherwise it looks good.

@jacquelinekay
Copy link
Contributor

+1

1 similar comment
@dirk-thomas
Copy link
Member

+1

@wjwwood
Copy link
Member Author

wjwwood commented Jun 21, 2016

I rebased and refactored the thread synchronization.

@wjwwood wjwwood merged commit 5e2a76c into master Jun 23, 2016
@wjwwood wjwwood deleted the wait_for_service2 branch June 23, 2016 03:18
@wjwwood wjwwood removed the in review Waiting for review (Kanban column) label Jun 23, 2016
Karsten1987 pushed a commit that referenced this pull request Dec 7, 2016
* add wait_for_service() and service_is_ready() to Client

* fix compile on Linux (maybe Windows)

* use visibility macros for Windows

* prevent unreasonable uncrustify change

* fixup comment

* add GraphListener::is_shutdown()

* disable copy on GraphListener

* use weak_ptr<Node> in client, throw if invalid

* ensure blocking wait_for_service wakes on rclcpp::shutdown/sigint

* rethrow exceptions after reporting them in thread

* lock ~Node() against notify_graph_change()

this essentially protects the notify_guard_condition_

* adjust thread sync strategy

* style

* moving initialization of wait set around, fix double free

* only fini wait set if started

* use rclcpp::shutdown to ensure graph listener resources clean up before static destruction

* uncrustify
nnmm pushed a commit to ApexAI/rclcpp that referenced this pull request Jul 9, 2022
* add missing documentation

* remove unnecessary visibility and warning macros
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants