ROS 2 rclcpp + rcl - jazzy  jazzy
ROS 2 C++ Client Library with ROS Client Library
context.hpp
1 // Copyright 2014 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 #ifndef RCLCPP__CONTEXT_HPP_
16 #define RCLCPP__CONTEXT_HPP_
17 
18 #include <condition_variable>
19 #include <functional>
20 #include <memory>
21 #include <mutex>
22 #include <string>
23 #include <typeindex>
24 #include <typeinfo>
25 #include <unordered_map>
26 #include <unordered_set>
27 #include <utility>
28 #include <vector>
29 #include <stdexcept>
30 
31 #include "rcl/context.h"
32 #include "rcl/guard_condition.h"
33 #include "rcl/wait.h"
34 #include "rclcpp/init_options.hpp"
35 #include "rclcpp/macros.hpp"
36 #include "rclcpp/visibility_control.hpp"
37 
38 namespace rclcpp
39 {
40 
42 class ContextAlreadyInitialized : public std::runtime_error
43 {
44 public:
46  : std::runtime_error("context is already initialized") {}
47 };
48 
51 
53 {
54  friend class Context;
55 
56 public:
57  using ShutdownCallbackType = std::function<void ()>;
58 
59 private:
60  std::weak_ptr<ShutdownCallbackType> callback;
61 };
62 
65 
67 
75 class Context : public std::enable_shared_from_this<Context>
76 {
77 public:
78  RCLCPP_SMART_PTR_DEFINITIONS(Context)
79 
80 
87  RCLCPP_PUBLIC
88  Context();
89 
90  RCLCPP_PUBLIC
91  virtual
92  ~Context();
93 
95 
129  RCLCPP_PUBLIC
130  virtual
131  void
132  init(
133  int argc,
134  char const * const * argv,
135  const rclcpp::InitOptions & init_options = rclcpp::InitOptions());
136 
138 
147  RCLCPP_PUBLIC
148  bool
149  is_valid() const;
150 
152  RCLCPP_PUBLIC
153  const rclcpp::InitOptions &
154  get_init_options() const;
155 
157  RCLCPP_PUBLIC
160 
162  RCLCPP_PUBLIC
163  size_t
164  get_domain_id() const;
165 
167 
170  RCLCPP_PUBLIC
171  std::string
172  shutdown_reason() const;
173 
175 
199  RCLCPP_PUBLIC
200  virtual
201  bool
202  shutdown(const std::string & reason);
203 
204  using OnShutdownCallback = OnShutdownCallbackHandle::ShutdownCallbackType;
205 
207 
225  RCLCPP_PUBLIC
226  virtual
227  OnShutdownCallback
228  on_shutdown(OnShutdownCallback callback);
229 
231 
249  RCLCPP_PUBLIC
250  virtual
252  add_on_shutdown_callback(OnShutdownCallback callback);
253 
255 
259  RCLCPP_PUBLIC
260  virtual
261  bool
262  remove_on_shutdown_callback(const OnShutdownCallbackHandle & callback_handle);
263 
264  using PreShutdownCallback = PreShutdownCallbackHandle::ShutdownCallbackType;
265 
267 
276  RCLCPP_PUBLIC
277  virtual
279  add_pre_shutdown_callback(PreShutdownCallback callback);
280 
282 
286  RCLCPP_PUBLIC
287  virtual
288  bool
290 
292 
295  RCLCPP_PUBLIC
296  std::vector<OnShutdownCallback>
298 
300 
303  RCLCPP_PUBLIC
304  std::vector<PreShutdownCallback>
306 
308  RCLCPP_PUBLIC
309  std::shared_ptr<rcl_context_t>
310  get_rcl_context();
311 
313 
324  RCLCPP_PUBLIC
325  bool
326  sleep_for(const std::chrono::nanoseconds & nanoseconds);
327 
329  RCLCPP_PUBLIC
330  void
332 
334  template<typename SubContext, typename ... Args>
335  std::shared_ptr<SubContext>
336  get_sub_context(Args && ... args)
337  {
338  std::lock_guard<std::recursive_mutex> lock(sub_contexts_mutex_);
339 
340  std::type_index type_i(typeid(SubContext));
341  std::shared_ptr<SubContext> sub_context;
342  auto it = sub_contexts_.find(type_i);
343  if (it == sub_contexts_.end()) {
344  // It doesn't exist yet, make it
345  sub_context = std::shared_ptr<SubContext>(
346  new SubContext(std::forward<Args>(args) ...),
347  [](SubContext * sub_context_ptr) {
348  delete sub_context_ptr;
349  });
350  sub_contexts_[type_i] = sub_context;
351  } else {
352  // It exists, get it out and cast it.
353  sub_context = std::static_pointer_cast<SubContext>(it->second);
354  }
355  return sub_context;
356  }
357 
358 protected:
359  // Called by constructor and destructor to clean up by finalizing the
360  // shutdown rcl context and preparing for a new init cycle.
361  RCLCPP_PUBLIC
362  void
363  clean_up();
364 
365 private:
366  RCLCPP_DISABLE_COPY(Context)
367 
368  // This mutex is recursive so that the destructor can ensure atomicity
369  // between is_initialized and shutdown.
370  mutable std::recursive_mutex init_mutex_;
371  std::shared_ptr<rcl_context_t> rcl_context_;
372  rclcpp::InitOptions init_options_;
373  std::string shutdown_reason_;
374 
375  // Keep shared ownership of the global logging mutex.
376  std::shared_ptr<std::recursive_mutex> logging_mutex_;
377 
378  std::unordered_map<std::type_index, std::shared_ptr<void>> sub_contexts_;
379  // This mutex is recursive so that the constructor of a sub context may
380  // attempt to acquire another sub context.
381  std::recursive_mutex sub_contexts_mutex_;
382 
383  std::vector<std::shared_ptr<OnShutdownCallback>> on_shutdown_callbacks_;
384  mutable std::mutex on_shutdown_callbacks_mutex_;
385 
386  std::vector<std::shared_ptr<PreShutdownCallback>> pre_shutdown_callbacks_;
387  mutable std::mutex pre_shutdown_callbacks_mutex_;
388 
390  std::condition_variable interrupt_condition_variable_;
392  std::mutex interrupt_mutex_;
393 
395  std::shared_ptr<WeakContextsWrapper> weak_contexts_;
396 
397  enum class ShutdownType
398  {
399  pre_shutdown,
401  };
402 
403  using ShutdownCallback = ShutdownCallbackHandle::ShutdownCallbackType;
404 
405  template<ShutdownType shutdown_type>
406  RCLCPP_LOCAL
407  ShutdownCallbackHandle
408  add_shutdown_callback(
409  ShutdownCallback callback);
410 
411  template<ShutdownType shutdown_type>
412  RCLCPP_LOCAL
413  bool
414  remove_shutdown_callback(
415  const ShutdownCallbackHandle & callback_handle);
416 
417  template<ShutdownType shutdown_type>
418  RCLCPP_LOCAL
419  std::vector<rclcpp::Context::ShutdownCallback>
420  get_shutdown_callback() const;
421 };
422 
424 
427 RCLCPP_PUBLIC
428 std::vector<Context::SharedPtr>
429 get_contexts();
430 
431 } // namespace rclcpp
432 
433 #endif // RCLCPP__CONTEXT_HPP_
Thrown when init is called on an already initialized context.
Definition: context.hpp:43
Context which encapsulates shared state between nodes and other similar entities.
Definition: context.hpp:76
std::shared_ptr< SubContext > get_sub_context(Args &&... args)
Return a singleton instance for the SubContext type, constructing one if necessary.
Definition: context.hpp:336
virtual RCLCPP_PUBLIC void init(int argc, char const *const *argv, const rclcpp::InitOptions &init_options=rclcpp::InitOptions())
Initialize the context, and the underlying elements like the rcl context.
Definition: context.cpp:238
RCLCPP_PUBLIC std::vector< OnShutdownCallback > get_on_shutdown_callbacks() const
Return the shutdown callbacks.
Definition: context.cpp:516
RCLCPP_PUBLIC std::vector< PreShutdownCallback > get_pre_shutdown_callbacks() const
Return the pre-shutdown callbacks.
Definition: context.cpp:522
RCLCPP_PUBLIC Context()
Default constructor, after which the Context is still not "initialized".
Definition: context.cpp:184
RCLCPP_PUBLIC size_t get_domain_id() const
Return actual domain id.
Definition: context.cpp:329
RCLCPP_PUBLIC std::string shutdown_reason() const
Return the shutdown reason, or empty string if not shutdown.
Definition: context.cpp:340
RCLCPP_PUBLIC const rclcpp::InitOptions & get_init_options() const
Return the init options used during init.
Definition: context.cpp:317
RCLCPP_PUBLIC bool sleep_for(const std::chrono::nanoseconds &nanoseconds)
Sleep for a given period of time or until shutdown() is called.
Definition: context.cpp:559
RCLCPP_PUBLIC void interrupt_all_sleep_for()
Interrupt any blocking sleep_for calls, causing them to return immediately and return true.
Definition: context.cpp:576
virtual RCLCPP_PUBLIC OnShutdownCallback on_shutdown(OnShutdownCallback callback)
Add a on_shutdown callback to be called when shutdown is called for this context.
Definition: context.cpp:420
virtual RCLCPP_PUBLIC OnShutdownCallbackHandle add_on_shutdown_callback(OnShutdownCallback callback)
Add a on_shutdown callback to be called when shutdown is called for this context.
Definition: context.cpp:427
virtual RCLCPP_PUBLIC bool remove_pre_shutdown_callback(const PreShutdownCallbackHandle &callback_handle)
Remove an registered pre_shutdown callback.
Definition: context.cpp:445
RCLCPP_PUBLIC bool is_valid() const
Return true if the context is valid, otherwise false.
Definition: context.cpp:306
virtual RCLCPP_PUBLIC PreShutdownCallbackHandle add_pre_shutdown_callback(PreShutdownCallback callback)
Add a pre_shutdown callback to be called before shutdown is called for this context.
Definition: context.cpp:439
virtual RCLCPP_PUBLIC bool remove_on_shutdown_callback(const OnShutdownCallbackHandle &callback_handle)
Remove an registered on_shutdown callbacks.
Definition: context.cpp:433
virtual RCLCPP_PUBLIC bool shutdown(const std::string &reason)
Shutdown the context, making it uninitialized and therefore invalid for derived entities.
Definition: context.cpp:347
RCLCPP_PUBLIC std::shared_ptr< rcl_context_t > get_rcl_context()
Return the internal rcl context.
Definition: context.cpp:553
Encapsulation of options for initializing rclcpp.
Class to manage vector of weak pointers to all created contexts.
Definition: context.cpp:44
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
RCLCPP_PUBLIC std::vector< Context::SharedPtr > get_contexts()
Return a copy of the list of context shared pointers.
Definition: context.cpp:590
RCLCPP_PUBLIC void on_shutdown(std::function< void()> callback, rclcpp::Context::SharedPtr context=nullptr)
Register a function to be called when shutdown is called on the context.