ROS 2 rclcpp + rcl - rolling  rolling-e7363f10
ROS 2 C++ Client Library with ROS Client Library
event.c
1 // Copyright 2019 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 #ifdef __cplusplus
16 extern "C"
17 {
18 #endif
19 
20 #include "rcl/event.h"
21 
22 #include <stdbool.h>
23 #include <stddef.h>
24 
25 #include "rcl/allocator.h"
26 #include "rcl/error_handling.h"
27 #include "rcl/types.h"
28 #include "rcutils/allocator.h"
29 #include "rcutils/error_handling.h"
30 #include "rcutils/logging_macros.h"
31 #include "rmw/error_handling.h"
32 #include "rmw/event.h"
33 #include "rmw/ret_types.h"
34 #include "rmw/rmw.h"
35 
36 #include "./common.h"
37 #include "./event_impl.h"
38 #include "./publisher_impl.h"
39 #include "./subscription_impl.h"
40 
43 {
44  // All members are initialized to 0 or NULL by C99 6.7.8/10.
45  static rcl_event_t null_event;
46  return null_event;
47 }
48 
51  rcl_event_t * event,
52  const rcl_publisher_t * publisher,
53  const rcl_publisher_event_type_t event_type)
54 {
55  RCL_CHECK_ARGUMENT_FOR_NULL(event, RCL_RET_EVENT_INVALID);
56  // Check publisher and allocator first, so allocator can be used with errors.
57  RCL_CHECK_ARGUMENT_FOR_NULL(publisher, RCL_RET_INVALID_ARGUMENT);
58  rcl_allocator_t * allocator = &publisher->impl->options.allocator;
59  RCL_CHECK_ALLOCATOR_WITH_MSG(allocator, "invalid allocator", return RCL_RET_INVALID_ARGUMENT);
60  rmw_event_type_t rmw_event_type = RMW_EVENT_INVALID;
61  switch (event_type) {
62  case RCL_PUBLISHER_OFFERED_DEADLINE_MISSED:
63  rmw_event_type = RMW_EVENT_OFFERED_DEADLINE_MISSED;
64  break;
65  case RCL_PUBLISHER_LIVELINESS_LOST:
66  rmw_event_type = RMW_EVENT_LIVELINESS_LOST;
67  break;
68  case RCL_PUBLISHER_OFFERED_INCOMPATIBLE_QOS:
69  rmw_event_type = RMW_EVENT_OFFERED_QOS_INCOMPATIBLE;
70  break;
71  case RCL_PUBLISHER_INCOMPATIBLE_TYPE:
72  rmw_event_type = RMW_EVENT_PUBLISHER_INCOMPATIBLE_TYPE;
73  break;
74  case RCL_PUBLISHER_MATCHED:
75  rmw_event_type = RMW_EVENT_PUBLICATION_MATCHED;
76  break;
77  }
78  if (rmw_event_type == RMW_EVENT_INVALID) {
79  RCL_SET_ERROR_MSG("Event type for publisher not supported");
81  }
82 
83  // Allocate space for the implementation struct.
84  event->impl = (rcl_event_impl_t *) allocator->allocate(
85  sizeof(rcl_event_impl_t), allocator->state);
86  RCL_CHECK_FOR_NULL_WITH_MSG(
87  event->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC);
88 
89  event->impl->rmw_handle = rmw_get_zero_initialized_event();
90  event->impl->allocator = *allocator;
91 
92  rmw_ret_t ret = rmw_publisher_event_init(
93  &event->impl->rmw_handle,
94  publisher->impl->rmw_handle,
95  rmw_event_type);
96  if (ret != RMW_RET_OK) {
97  goto fail;
98  }
99 
100  return RCL_RET_OK;
101 fail:
102  allocator->deallocate(event->impl, allocator->state);
103  event->impl = NULL;
104  return rcl_convert_rmw_ret_to_rcl_ret(ret);
105 }
106 
107 rcl_ret_t
109  rcl_event_t * event,
110  const rcl_subscription_t * subscription,
111  const rcl_subscription_event_type_t event_type)
112 {
113  RCL_CHECK_ARGUMENT_FOR_NULL(event, RCL_RET_EVENT_INVALID);
114  // Check subscription and allocator first, so allocator can be used with errors.
115  RCL_CHECK_ARGUMENT_FOR_NULL(subscription, RCL_RET_INVALID_ARGUMENT);
116  rcl_allocator_t * allocator = &subscription->impl->options.allocator;
117  RCL_CHECK_ALLOCATOR_WITH_MSG(allocator, "invalid allocator", return RCL_RET_INVALID_ARGUMENT);
118  rmw_event_type_t rmw_event_type = RMW_EVENT_INVALID;
119  switch (event_type) {
120  case RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED:
121  rmw_event_type = RMW_EVENT_REQUESTED_DEADLINE_MISSED;
122  break;
123  case RCL_SUBSCRIPTION_LIVELINESS_CHANGED:
124  rmw_event_type = RMW_EVENT_LIVELINESS_CHANGED;
125  break;
126  case RCL_SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS:
127  rmw_event_type = RMW_EVENT_REQUESTED_QOS_INCOMPATIBLE;
128  break;
129  case RCL_SUBSCRIPTION_MESSAGE_LOST:
130  rmw_event_type = RMW_EVENT_MESSAGE_LOST;
131  break;
132  case RCL_SUBSCRIPTION_INCOMPATIBLE_TYPE:
133  rmw_event_type = RMW_EVENT_SUBSCRIPTION_INCOMPATIBLE_TYPE;
134  break;
135  case RCL_SUBSCRIPTION_MATCHED:
136  rmw_event_type = RMW_EVENT_SUBSCRIPTION_MATCHED;
137  break;
138  }
139  if (rmw_event_type == RMW_EVENT_INVALID) {
140  RCL_SET_ERROR_MSG("Event type for subscription not supported");
142  }
143 
144  // Allocate space for the implementation struct.
145  event->impl = (rcl_event_impl_t *) allocator->allocate(
146  sizeof(rcl_event_impl_t), allocator->state);
147  RCL_CHECK_FOR_NULL_WITH_MSG(
148  event->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC);
149 
150  event->impl->rmw_handle = rmw_get_zero_initialized_event();
151  event->impl->allocator = *allocator;
152 
153  rmw_ret_t ret = rmw_subscription_event_init(
154  &event->impl->rmw_handle,
155  subscription->impl->rmw_handle,
156  rmw_event_type);
157  if (ret != RMW_RET_OK) {
158  goto fail;
159  }
160 
161  return RCL_RET_OK;
162 fail:
163  allocator->deallocate(event->impl, allocator->state);
164  event->impl = NULL;
165  return rcl_convert_rmw_ret_to_rcl_ret(ret);
166 }
167 
168 rcl_ret_t
170  const rcl_event_t * event,
171  void * event_info)
172 {
173  bool taken = false;
174  if (!rcl_event_is_valid(event)) {
175  return RCL_RET_EVENT_INVALID;
176  }
177  RCL_CHECK_ARGUMENT_FOR_NULL(event_info, RCL_RET_INVALID_ARGUMENT);
178  rmw_ret_t ret = rmw_take_event(&event->impl->rmw_handle, event_info, &taken);
179  if (RMW_RET_OK != ret) {
180  RCL_SET_ERROR_MSG(rmw_get_error_string().str);
181  return rcl_convert_rmw_ret_to_rcl_ret(ret);
182  }
183  if (!taken) {
184  RCUTILS_LOG_DEBUG_NAMED(
185  ROS_PACKAGE_NAME, "take_event request complete, unable to take event");
187  }
188  RCUTILS_LOG_DEBUG_NAMED(
189  ROS_PACKAGE_NAME, "take_event request success");
190  return rcl_convert_rmw_ret_to_rcl_ret(ret);
191 }
192 
193 rcl_ret_t
195 {
196  rcl_ret_t result = RCL_RET_OK;
197  RCL_CHECK_ARGUMENT_FOR_NULL(event, RCL_RET_EVENT_INVALID);
198 
199  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Finalizing event");
200  if (NULL != event->impl) {
201  rcl_allocator_t allocator = event->impl->allocator;
202  rmw_ret_t ret = rmw_event_fini(&event->impl->rmw_handle);
203  if (ret != RMW_RET_OK) {
204  RCL_SET_ERROR_MSG(rmw_get_error_string().str);
205  result = rcl_convert_rmw_ret_to_rcl_ret(ret);
206  }
207  allocator.deallocate(event->impl, allocator.state);
208  event->impl = NULL;
209  }
210  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Event finalized");
211 
212  return result;
213 }
214 
215 rmw_event_t *
217 {
218  if (!rcl_event_is_valid(event)) {
219  return NULL; // error already set
220  } else {
221  return &event->impl->rmw_handle;
222  }
223 }
224 
225 bool
227 {
228  RCL_CHECK_FOR_NULL_WITH_MSG(event, "event pointer is invalid", return false);
229  RCL_CHECK_FOR_NULL_WITH_MSG(event->impl, "event's implementation is invalid", return false);
230  if (event->impl->rmw_handle.event_type == RMW_EVENT_INVALID) {
231  RCUTILS_SET_ERROR_MSG("event's implementation not init");
232  return false;
233  }
234  RCUTILS_CHECK_ALLOCATOR_WITH_MSG(
235  &event->impl->allocator, "not valid allocator", return false);
236  return true;
237 }
238 
239 bool
241  const rcl_publisher_event_type_t event_type)
242 {
243  rmw_event_type_t rmw_event_type = RMW_EVENT_INVALID;
244  switch (event_type) {
245  case RCL_PUBLISHER_OFFERED_DEADLINE_MISSED:
246  rmw_event_type = RMW_EVENT_OFFERED_DEADLINE_MISSED;
247  break;
248  case RCL_PUBLISHER_LIVELINESS_LOST:
249  rmw_event_type = RMW_EVENT_LIVELINESS_LOST;
250  break;
251  case RCL_PUBLISHER_OFFERED_INCOMPATIBLE_QOS:
252  rmw_event_type = RMW_EVENT_OFFERED_QOS_INCOMPATIBLE;
253  break;
254  case RCL_PUBLISHER_INCOMPATIBLE_TYPE:
255  rmw_event_type = RMW_EVENT_PUBLISHER_INCOMPATIBLE_TYPE;
256  break;
257  case RCL_PUBLISHER_MATCHED:
258  rmw_event_type = RMW_EVENT_PUBLICATION_MATCHED;
259  break;
260  }
261  if (rmw_event_type == RMW_EVENT_INVALID) {
262  return false;
263  }
264  return rmw_event_type_is_supported(rmw_event_type);
265 }
266 
267 bool
269  const rcl_subscription_event_type_t event_type)
270 {
271  rmw_event_type_t rmw_event_type = RMW_EVENT_INVALID;
272  switch (event_type) {
273  case RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED:
274  rmw_event_type = RMW_EVENT_REQUESTED_DEADLINE_MISSED;
275  break;
276  case RCL_SUBSCRIPTION_LIVELINESS_CHANGED:
277  rmw_event_type = RMW_EVENT_LIVELINESS_CHANGED;
278  break;
279  case RCL_SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS:
280  rmw_event_type = RMW_EVENT_REQUESTED_QOS_INCOMPATIBLE;
281  break;
282  case RCL_SUBSCRIPTION_MESSAGE_LOST:
283  rmw_event_type = RMW_EVENT_MESSAGE_LOST;
284  break;
285  case RCL_SUBSCRIPTION_INCOMPATIBLE_TYPE:
286  rmw_event_type = RMW_EVENT_SUBSCRIPTION_INCOMPATIBLE_TYPE;
287  break;
288  case RCL_SUBSCRIPTION_MATCHED:
289  rmw_event_type = RMW_EVENT_SUBSCRIPTION_MATCHED;
290  break;
291  }
292  if (rmw_event_type == RMW_EVENT_INVALID) {
293  return false;
294  }
295  return rmw_event_type_is_supported(rmw_event_type);
296 }
297 
298 rcl_ret_t
300  const rcl_event_t * event,
301  rcl_event_callback_t callback,
302  const void * user_data)
303 {
304  if (!rcl_event_is_valid(event)) {
305  // error state already set
307  }
308 
309  return rmw_event_set_callback(
310  &event->impl->rmw_handle,
311  callback,
312  user_data);
313 }
314 
315 #ifdef __cplusplus
316 }
317 #endif
#define RCL_CHECK_ALLOCATOR_WITH_MSG(allocator, msg, fail_statement)
Check that the given allocator is initialized, or fail with a message.
Definition: allocator.h:56
rcutils_allocator_t rcl_allocator_t
Encapsulation of an allocator.
Definition: allocator.h:31
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_take_event(const rcl_event_t *event, void *event_info)
Definition: event.c:169
enum rcl_publisher_event_type_e rcl_publisher_event_type_t
Enumeration of all of the publisher events that may fire.
RCL_PUBLIC RCL_WARN_UNUSED rcl_event_t rcl_get_zero_initialized_event(void)
Return a rcl_event_t struct with members set to NULL.
Definition: event.c:42
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_event_set_callback(const rcl_event_t *event, rcl_event_callback_t callback, const void *user_data)
Set the callback function for the event.
Definition: event.c:299
enum rcl_subscription_event_type_e rcl_subscription_event_type_t
Enumeration of all of the subscription events that may fire.
RCL_PUBLIC RCL_WARN_UNUSED rmw_event_t * rcl_event_get_rmw_handle(const rcl_event_t *event)
Return the rmw event handle.
Definition: event.c:216
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_subscription_event_init(rcl_event_t *event, const rcl_subscription_t *subscription, const rcl_subscription_event_type_t event_type)
Initialize an rcl_event_t with a subscription.
Definition: event.c:108
RCL_PUBLIC RCL_WARN_UNUSED bool rcl_subscription_event_type_is_supported(const rcl_subscription_event_type_t event_type)
Check if a subscription event type is supported by the active RMW implementation.
Definition: event.c:268
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_event_fini(rcl_event_t *event)
Definition: event.c:194
RCL_PUBLIC bool rcl_event_is_valid(const rcl_event_t *event)
Check that the event is valid.
Definition: event.c:226
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_publisher_event_init(rcl_event_t *event, const rcl_publisher_t *publisher, const rcl_publisher_event_type_t event_type)
Initialize an rcl_event_t with a publisher.
Definition: event.c:50
RCL_PUBLIC RCL_WARN_UNUSED bool rcl_publisher_event_type_is_supported(const rcl_publisher_event_type_t event_type)
Check if a publisher event type is supported by the active RMW implementation.
Definition: event.c:240
Structure which encapsulates a ROS QoS event handle.
Definition: event.h:64
rcl_event_impl_t * impl
Pointer to the event implementation.
Definition: event.h:66
rcl_allocator_t allocator
Custom allocator for the publisher, used for incidental allocations.
Definition: publisher.h:56
Structure which encapsulates a ROS Publisher.
Definition: publisher.h:44
rcl_publisher_impl_t * impl
Pointer to the publisher implementation.
Definition: publisher.h:46
rcl_allocator_t allocator
Custom allocator for the subscription, used for incidental allocations.
Definition: subscription.h:60
Structure which encapsulates a ROS Subscription.
Definition: subscription.h:48
rcl_subscription_impl_t * impl
Pointer to the subscription implementation.
Definition: subscription.h:50
#define RCL_RET_EVENT_TAKE_FAILED
Failed to take an event from the event handle.
Definition: types.h:122
#define RCL_RET_OK
Success return code.
Definition: types.h:28
#define RCL_RET_BAD_ALLOC
Failed to allocate memory return code.
Definition: types.h:34
#define RCL_RET_INVALID_ARGUMENT
Invalid argument return code.
Definition: types.h:36
#define RCL_RET_EVENT_INVALID
Invalid rcl_event_t given return code.
Definition: types.h:120
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
Definition: types.h:25