ROS 2 rclcpp + rcl - jazzy  jazzy
ROS 2 C++ Client Library with ROS Client Library
guard_condition.cpp
1 // Copyright 2020 Open Source Robotics Foundation, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <functional>
16 
17 #include "rclcpp/guard_condition.hpp"
18 
19 #include "rclcpp/exceptions.hpp"
20 #include "rclcpp/logging.hpp"
21 
22 namespace rclcpp
23 {
24 
26  const rclcpp::Context::SharedPtr & context,
27  rcl_guard_condition_options_t guard_condition_options)
28 : rcl_guard_condition_{rcl_get_zero_initialized_guard_condition()}
29 {
30  if (!context) {
31  throw std::invalid_argument("context argument unexpectedly nullptr");
32  }
33 
35  &this->rcl_guard_condition_,
36  context->get_rcl_context().get(),
37  guard_condition_options);
38  if (RCL_RET_OK != ret) {
39  rclcpp::exceptions::throw_from_rcl_error(ret, "failed to create guard condition");
40  }
41 }
42 
43 GuardCondition::~GuardCondition()
44 {
45  rcl_ret_t ret = rcl_guard_condition_fini(&this->rcl_guard_condition_);
46  if (RCL_RET_OK != ret) {
47  try {
48  rclcpp::exceptions::throw_from_rcl_error(ret);
49  } catch (const std::exception & exception) {
50  RCLCPP_ERROR(
51  rclcpp::get_logger("rclcpp"),
52  "failed to finalize guard condition: %s", exception.what());
53  }
54  }
55 }
56 
59 {
60  return rcl_guard_condition_;
61 }
62 
65 {
66  return rcl_guard_condition_;
67 }
68 
69 void
71 {
72  rcl_ret_t ret = rcl_trigger_guard_condition(&rcl_guard_condition_);
73  if (RCL_RET_OK != ret) {
74  rclcpp::exceptions::throw_from_rcl_error(ret);
75  }
76 
77  {
78  std::lock_guard<std::recursive_mutex> lock(reentrant_mutex_);
79 
80  if (on_trigger_callback_) {
81  on_trigger_callback_(1);
82  } else {
83  unread_count_++;
84  }
85  }
86 }
87 
88 bool
90 {
91  return in_use_by_wait_set_.exchange(in_use_state);
92 }
93 
94 void
96 {
97  std::lock_guard<std::recursive_mutex> lock(reentrant_mutex_);
98 
100  if (&wait_set != wait_set_) {
101  throw std::runtime_error("guard condition has already been added to a wait set.");
102  }
103  } else {
104  wait_set_ = &wait_set;
105  }
106 
107  rcl_ret_t ret = rcl_wait_set_add_guard_condition(&wait_set, &this->rcl_guard_condition_, NULL);
108  if (RCL_RET_OK != ret) {
109  rclcpp::exceptions::throw_from_rcl_error(
110  ret, "failed to add guard condition to wait set");
111  }
112 }
113 
114 void
115 GuardCondition::set_on_trigger_callback(std::function<void(size_t)> callback)
116 {
117  std::lock_guard<std::recursive_mutex> lock(reentrant_mutex_);
118 
119  if (callback) {
120  on_trigger_callback_ = callback;
121 
122  if (unread_count_) {
123  callback(unread_count_);
124  unread_count_ = 0;
125  }
126  } else {
127  on_trigger_callback_ = nullptr;
128  }
129 }
130 
131 } // namespace rclcpp
RCLCPP_PUBLIC void trigger()
Signal that the condition has been met, notifying both the wait set and listeners,...
RCLCPP_PUBLIC GuardCondition(const rclcpp::Context::SharedPtr &context=rclcpp::contexts::get_global_default_context(), rcl_guard_condition_options_t guard_condition_options=rcl_guard_condition_get_default_options())
Construct the guard condition, optionally specifying which Context to use.
RCLCPP_PUBLIC rcl_guard_condition_t & get_rcl_guard_condition()
Return the underlying rcl guard condition structure.
RCLCPP_PUBLIC void set_on_trigger_callback(std::function< void(size_t)> callback)
Set a callback to be called whenever the guard condition is triggered.
RCLCPP_PUBLIC void add_to_wait_set(rcl_wait_set_t &wait_set)
Adds the guard condition to a waitset.
RCLCPP_PUBLIC bool exchange_in_use_by_wait_set_state(bool in_use_state)
Exchange the "in use by wait set" state for this guard condition.
RCL_PUBLIC RCL_WARN_UNUSED rcl_guard_condition_t rcl_get_zero_initialized_guard_condition(void)
Return a rcl_guard_condition_t struct with members set to NULL.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_trigger_guard_condition(rcl_guard_condition_t *guard_condition)
Trigger a rcl guard condition.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_guard_condition_init(rcl_guard_condition_t *guard_condition, rcl_context_t *context, const rcl_guard_condition_options_t options)
Initialize a rcl guard_condition.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_guard_condition_fini(rcl_guard_condition_t *guard_condition)
Finalize a rcl_guard_condition_t.
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
RCLCPP_PUBLIC Logger get_logger(const std::string &name)
Return a named logger.
Definition: logger.cpp:33
Options available for a rcl guard condition.
Handle for a rcl guard condition.
Container for subscription's, guard condition's, etc to be waited on.
Definition: wait.h:42
#define RCL_RET_OK
Success return code.
Definition: types.h:27
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
Definition: types.h:24
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_set_add_guard_condition(rcl_wait_set_t *wait_set, const rcl_guard_condition_t *guard_condition, size_t *index)
Store a pointer to the guard condition in the next empty spot in the set.
Definition: wait.c:454