15 #ifndef RCLCPP__WAIT_RESULT_HPP_
16 #define RCLCPP__WAIT_RESULT_HPP_
27 #include "rclcpp/macros.hpp"
28 #include "rclcpp/wait_result_kind.hpp"
30 #include "rclcpp/client.hpp"
31 #include "rclcpp/service.hpp"
32 #include "rclcpp/subscription_base.hpp"
33 #include "rclcpp/timer.hpp"
61 template<
class WaitSetT>
75 return WaitResult(WaitResultKind::Ready, wait_set);
98 return wait_result_kind_;
109 if (this->
kind() != WaitResultKind::Ready) {
110 throw std::runtime_error(
"cannot access wait set when the result was not ready");
113 assert(wait_set_pointer_);
114 return *wait_set_pointer_;
125 if (this->
kind() != WaitResultKind::Ready) {
126 throw std::runtime_error(
"cannot access wait set when the result was not ready");
129 assert(wait_set_pointer_);
130 return *wait_set_pointer_;
134 : wait_result_kind_(other.wait_result_kind_),
135 wait_set_pointer_(std::exchange(other.wait_set_pointer_,
nullptr))
140 if (wait_set_pointer_) {
141 wait_set_pointer_->wait_result_release();
167 std::pair<std::shared_ptr<rclcpp::TimerBase>,
size_t>
170 check_wait_result_dirty();
171 auto ret = std::shared_ptr<rclcpp::TimerBase>{
nullptr};
172 size_t ii = start_index;
173 if (this->
kind() == WaitResultKind::Ready) {
175 auto & rcl_wait_set = wait_set.storage_get_rcl_wait_set();
176 for (; ii < wait_set.size_of_timers(); ++ii) {
177 if (rcl_wait_set.timers[ii] !=
nullptr) {
178 ret = wait_set.timers(ii);
202 auto & rcl_wait_set = wait_set.storage_get_rcl_wait_set();
203 if (index >= wait_set.size_of_timers()) {
204 throw std::out_of_range(
"given timer index is out of range");
206 rcl_wait_set.timers[index] =
nullptr;
210 std::shared_ptr<rclcpp::SubscriptionBase>
213 check_wait_result_dirty();
214 auto ret = std::shared_ptr<rclcpp::SubscriptionBase>{
nullptr};
215 if (this->
kind() == WaitResultKind::Ready) {
217 auto & rcl_wait_set = wait_set.storage_get_rcl_wait_set();
218 for (
size_t ii = 0; ii < wait_set.size_of_subscriptions(); ++ii) {
219 if (rcl_wait_set.subscriptions[ii] !=
nullptr) {
220 ret = wait_set.subscriptions(ii);
221 rcl_wait_set.subscriptions[ii] =
nullptr;
232 std::shared_ptr<rclcpp::ServiceBase>
235 check_wait_result_dirty();
236 auto ret = std::shared_ptr<rclcpp::ServiceBase>{
nullptr};
237 if (this->
kind() == WaitResultKind::Ready) {
239 auto & rcl_wait_set = wait_set.storage_get_rcl_wait_set();
240 for (
size_t ii = 0; ii < wait_set.size_of_services(); ++ii) {
241 if (rcl_wait_set.services[ii] !=
nullptr) {
242 ret = wait_set.services(ii);
243 rcl_wait_set.services[ii] =
nullptr;
254 std::shared_ptr<rclcpp::ClientBase>
257 check_wait_result_dirty();
258 auto ret = std::shared_ptr<rclcpp::ClientBase>{
nullptr};
259 if (this->
kind() == WaitResultKind::Ready) {
261 auto & rcl_wait_set = wait_set.storage_get_rcl_wait_set();
262 for (
size_t ii = 0; ii < wait_set.size_of_clients(); ++ii) {
263 if (rcl_wait_set.clients[ii] !=
nullptr) {
264 ret = wait_set.clients(ii);
265 rcl_wait_set.clients[ii] =
nullptr;
276 std::shared_ptr<rclcpp::Waitable>
279 check_wait_result_dirty();
280 auto waitable = std::shared_ptr<rclcpp::Waitable>{
nullptr};
281 auto data = std::shared_ptr<void>{
nullptr};
283 if (this->
kind() == WaitResultKind::Ready) {
285 auto & rcl_wait_set = wait_set.get_rcl_wait_set();
286 while (next_waitable_index_ < wait_set.size_of_waitables()) {
287 auto cur_waitable = wait_set.waitables(next_waitable_index_++);
288 if (cur_waitable !=
nullptr && cur_waitable->is_ready(rcl_wait_set)) {
289 waitable = cur_waitable;
301 explicit WaitResult(WaitResultKind wait_result_kind)
302 : wait_result_kind_(wait_result_kind)
305 assert(WaitResultKind::Ready != wait_result_kind);
308 WaitResult(WaitResultKind wait_result_kind, WaitSetT & wait_set)
309 : wait_result_kind_(wait_result_kind),
310 wait_set_pointer_(&wait_set)
313 assert(WaitResultKind::Ready == wait_result_kind);
320 check_wait_result_dirty()
324 if (wait_set_pointer_ && this->
get_wait_set().wait_result_dirty_) {
325 this->wait_result_kind_ = WaitResultKind::Invalid;
329 WaitResultKind wait_result_kind_;
331 WaitSetT * wait_set_pointer_ =
nullptr;
333 size_t next_waitable_index_ = 0;
Interface for introspecting a wait set after waiting on it.
std::shared_ptr< rclcpp::SubscriptionBase > next_ready_subscription()
Get the next ready subscription, clearing it from the wait result.
std::pair< std::shared_ptr< rclcpp::TimerBase >, size_t > peek_next_ready_timer(size_t start_index=0)
Get the next ready timer and its index in the wait result, but do not clear it.
static WaitResult from_ready_wait_result_kind(WaitSetT &wait_set)
Create WaitResult from a "ready" result.
static WaitResult from_empty_wait_result_kind()
Create WaitResult from a "empty" result.
static WaitResult from_timeout_wait_result_kind()
Create WaitResult from a "timeout" result.
std::shared_ptr< rclcpp::ServiceBase > next_ready_service()
Get the next ready service, clearing it from the wait result.
const WaitSetT & get_wait_set() const
Return the rcl wait set.
WaitResultKind kind() const
Return the kind of the WaitResult.
void clear_timer_with_index(size_t index)
Clear the timer at the given index.
std::shared_ptr< rclcpp::ClientBase > next_ready_client()
Get the next ready client, clearing it from the wait result.
WaitSetT & get_wait_set()
Return the rcl wait set.
std::shared_ptr< rclcpp::Waitable > next_ready_waitable()
Get the next ready waitable, clearing it from the wait result.
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.