ROS 2 rclcpp + rcl - humble  humble
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 
72 class Context : public std::enable_shared_from_this<Context>
73 {
74 public:
75  RCLCPP_SMART_PTR_DEFINITIONS(Context)
76 
77 
84  RCLCPP_PUBLIC
85  Context();
86 
87  RCLCPP_PUBLIC
88  virtual
89  ~Context();
90 
92 
126  RCLCPP_PUBLIC
127  virtual
128  void
129  init(
130  int argc,
131  char const * const * argv,
132  const rclcpp::InitOptions & init_options = rclcpp::InitOptions());
133 
135 
144  RCLCPP_PUBLIC
145  bool
146  is_valid() const;
147 
149  RCLCPP_PUBLIC
150  const rclcpp::InitOptions &
151  get_init_options() const;
152 
154  RCLCPP_PUBLIC
157 
159  RCLCPP_PUBLIC
160  size_t
161  get_domain_id() const;
162 
164 
167  RCLCPP_PUBLIC
168  std::string
169  shutdown_reason() const;
170 
172 
191  RCLCPP_PUBLIC
192  virtual
193  bool
194  shutdown(const std::string & reason);
195 
196  using OnShutdownCallback = OnShutdownCallbackHandle::ShutdownCallbackType;
197 
199 
217  RCLCPP_PUBLIC
218  virtual
219  OnShutdownCallback
220  on_shutdown(OnShutdownCallback callback);
221 
223 
241  RCLCPP_PUBLIC
242  virtual
244  add_on_shutdown_callback(OnShutdownCallback callback);
245 
247 
251  RCLCPP_PUBLIC
252  virtual
253  bool
254  remove_on_shutdown_callback(const OnShutdownCallbackHandle & callback_handle);
255 
256  using PreShutdownCallback = PreShutdownCallbackHandle::ShutdownCallbackType;
257 
259 
268  RCLCPP_PUBLIC
269  virtual
271  add_pre_shutdown_callback(PreShutdownCallback callback);
272 
274 
278  RCLCPP_PUBLIC
279  virtual
280  bool
282 
284 
287  RCLCPP_PUBLIC
288  std::vector<OnShutdownCallback>
290 
292 
295  RCLCPP_PUBLIC
296  std::vector<PreShutdownCallback>
298 
300  RCLCPP_PUBLIC
301  std::shared_ptr<rcl_context_t>
302  get_rcl_context();
303 
305 
316  RCLCPP_PUBLIC
317  bool
318  sleep_for(const std::chrono::nanoseconds & nanoseconds);
319 
321  RCLCPP_PUBLIC
322  virtual
323  void
325 
327  template<typename SubContext, typename ... Args>
328  std::shared_ptr<SubContext>
329  get_sub_context(Args && ... args)
330  {
331  std::lock_guard<std::recursive_mutex> lock(sub_contexts_mutex_);
332 
333  std::type_index type_i(typeid(SubContext));
334  std::shared_ptr<SubContext> sub_context;
335  auto it = sub_contexts_.find(type_i);
336  if (it == sub_contexts_.end()) {
337  // It doesn't exist yet, make it
338  sub_context = std::shared_ptr<SubContext>(
339  new SubContext(std::forward<Args>(args) ...),
340  [](SubContext * sub_context_ptr) {
341  delete sub_context_ptr;
342  });
343  sub_contexts_[type_i] = sub_context;
344  } else {
345  // It exists, get it out and cast it.
346  sub_context = std::static_pointer_cast<SubContext>(it->second);
347  }
348  return sub_context;
349  }
350 
351 protected:
352  // Called by constructor and destructor to clean up by finalizing the
353  // shutdown rcl context and preparing for a new init cycle.
354  RCLCPP_PUBLIC
355  virtual
356  void
357  clean_up();
358 
359 private:
360  RCLCPP_DISABLE_COPY(Context)
361 
362  // This mutex is recursive so that the destructor can ensure atomicity
363  // between is_initialized and shutdown.
364  mutable std::recursive_mutex init_mutex_;
365  std::shared_ptr<rcl_context_t> rcl_context_;
366  rclcpp::InitOptions init_options_;
367  std::string shutdown_reason_;
368 
369  // Keep shared ownership of the global logging mutex.
370  std::shared_ptr<std::recursive_mutex> logging_mutex_;
371 
372  std::unordered_map<std::type_index, std::shared_ptr<void>> sub_contexts_;
373  // This mutex is recursive so that the constructor of a sub context may
374  // attempt to acquire another sub context.
375  std::recursive_mutex sub_contexts_mutex_;
376 
377  std::unordered_set<std::shared_ptr<OnShutdownCallback>> on_shutdown_callbacks_;
378  mutable std::mutex on_shutdown_callbacks_mutex_;
379 
380  std::unordered_set<std::shared_ptr<PreShutdownCallback>> pre_shutdown_callbacks_;
381  mutable std::mutex pre_shutdown_callbacks_mutex_;
382 
384  std::condition_variable interrupt_condition_variable_;
386  std::mutex interrupt_mutex_;
387 
389  std::shared_ptr<WeakContextsWrapper> weak_contexts_;
390 
391  enum class ShutdownType
392  {
393  pre_shutdown,
395  };
396 
397  using ShutdownCallback = ShutdownCallbackHandle::ShutdownCallbackType;
398 
399  RCLCPP_LOCAL
400  ShutdownCallbackHandle
401  add_shutdown_callback(
402  ShutdownType shutdown_type,
403  ShutdownCallback callback);
404 
405  RCLCPP_LOCAL
406  bool
407  remove_shutdown_callback(
408  ShutdownType shutdown_type,
409  const ShutdownCallbackHandle & callback_handle);
410 
411  std::vector<rclcpp::Context::ShutdownCallback>
412  get_shutdown_callback(ShutdownType shutdown_type) const;
413 };
414 
416 
419 RCLCPP_PUBLIC
420 std::vector<Context::SharedPtr>
421 get_contexts();
422 
423 } // namespace rclcpp
424 
425 #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:73
std::shared_ptr< SubContext > get_sub_context(Args &&... args)
Return a singleton instance for the SubContext type, constructing one if necessary.
Definition: context.hpp:329
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:191
RCLCPP_PUBLIC std::vector< OnShutdownCallback > get_on_shutdown_callbacks() const
Return the shutdown callbacks.
Definition: context.cpp:445
RCLCPP_PUBLIC std::vector< PreShutdownCallback > get_pre_shutdown_callbacks() const
Return the pre-shutdown callbacks.
Definition: context.cpp:451
RCLCPP_PUBLIC Context()
Default constructor, after which the Context is still not "initialized".
Definition: context.cpp:145
RCLCPP_PUBLIC size_t get_domain_id() const
Return actual domain id.
Definition: context.cpp:282
RCLCPP_PUBLIC std::string shutdown_reason() const
Return the shutdown reason, or empty string if not shutdown.
Definition: context.cpp:293
RCLCPP_PUBLIC const rclcpp::InitOptions & get_init_options() const
Return the init options used during init.
Definition: context.cpp:270
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:492
virtual RCLCPP_PUBLIC void interrupt_all_sleep_for()
Interrupt any blocking sleep_for calls, causing them to return immediately and return true.
Definition: context.cpp:509
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:357
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:364
virtual RCLCPP_PUBLIC bool remove_pre_shutdown_callback(const PreShutdownCallbackHandle &callback_handle)
Remove an registered pre_shutdown callback.
Definition: context.cpp:382
RCLCPP_PUBLIC bool is_valid() const
Return true if the context is valid, otherwise false.
Definition: context.cpp:259
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:376
virtual RCLCPP_PUBLIC bool remove_on_shutdown_callback(const OnShutdownCallbackHandle &callback_handle)
Remove an registered on_shutdown callbacks.
Definition: context.cpp:370
virtual RCLCPP_PUBLIC bool shutdown(const std::string &reason)
Shutdown the context, making it uninitialized and therefore invalid for derived entities.
Definition: context.cpp:300
RCLCPP_PUBLIC std::shared_ptr< rcl_context_t > get_rcl_context()
Return the internal rcl context.
Definition: context.cpp:486
Encapsulation of options for initializing rclcpp.
Class to manage vector of weak pointers to all created contexts.
Definition: context.cpp:43
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:523
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.