rmw  master
C API providing a middleware abstraction layer which is used to implement the rest of ROS.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
macros.hpp
Go to the documentation of this file.
1 // Copyright 2015 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 RMW__IMPL__CPP__MACROS_HPP_
16 #define RMW__IMPL__CPP__MACROS_HPP_
17 
18 #include <iostream>
19 #include <sstream>
20 #include <string>
21 
22 #include "rcutils/snprintf.h"
23 
24 #include "rmw/allocators.h"
25 #include "rmw/error_handling.h"
26 #include "rmw/impl/config.h" // For RMW_AVOID_MEMORY_ALLOCATION
27 #include "rmw/impl/cpp/demangle.hpp" // For demangle.
28 
29 #define RMW_TRY_PLACEMENT_NEW(Destination, BufferForNew, FailureAction, Type, ...) \
30  try { \
31  Destination = new(BufferForNew) Type(__VA_ARGS__); \
32  } catch (const std::exception & exception) { \
33  RMW_SET_ERROR_MSG( \
34  ( \
35  std::string("caught C++ exception ") + rmw::impl::cpp::demangle(exception) + \
36  " constructing " #Type ": " + exception.what() \
37  ).c_str()); \
38  FailureAction; \
39  } catch (...) { \
40  RMW_SET_ERROR_MSG("caught unknown C++ exception constructing " #Type); \
41  FailureAction; \
42  }
43 
44 #define RMW_TRY_DESTRUCTOR(Statement, Type, FailureAction) \
45  try { \
46  Statement; \
47  } catch (const std::exception & exception) { \
48  RMW_SET_ERROR_MSG( \
49  ( \
50  std::string("caught C++ exception in destructor of " #Type ": ") + \
51  rmw::impl::cpp::demangle(exception) + ": " + exception.what() \
52  ).c_str()); \
53  FailureAction; \
54  } catch (...) { \
55  RMW_SET_ERROR_MSG("caught unknown C++ exception in destructor of " #Type); \
56  FailureAction; \
57  }
58 
59 #define RMW_TRY_DESTRUCTOR_FROM_WITHIN_FAILURE(Statement, Type) \
60  try { \
61  Statement; \
62  } catch (const std::exception & exception) { \
63  std::stringstream ss; \
64  ss << "caught C++ exception in destructor of " #Type " while handling a failure: " \
65  << rmw::impl::cpp::demangle(exception) << ": " << exception.what() \
66  << ", at: " << __FILE__ << ":" << __LINE__ << '\n'; \
67  (std::cerr << ss.str()).flush(); \
68  } catch (...) { \
69  std::stringstream ss; \
70  ss << "caught unknown C++ exception in destructor of " #Type << \
71  " while handling a failure at: " << __FILE__ << ":" << __LINE__ << '\n'; \
72  (std::cerr << ss.str()).flush(); \
73  }
74 
75 #if RMW_AVOID_MEMORY_ALLOCATION
76 #define RMW_CHECK_TYPE_IDENTIFIERS_MATCH(ElementName, ElementTypeID, ExpectedTypeID, OnFailure) \
77  { \
78  if (ElementTypeID != ExpectedTypeID) { \
79  char __msg[1024]; \
80  int ret = rcutils_snprintf( \
81  __msg, sizeof(__msg), \
82  #ElementName " implementation '%s'(%p) does not match rmw implementation '%s'(%p)", \
83  ElementTypeID, reinterpret_cast<const void *>(ElementTypeID), \
84  ExpectedTypeID, reinterpret_cast<const void *>(ExpectedTypeID)); \
85  if (ret < 0) { \
86  static const char error_msg[] = \
87  "RMW_CHECK_TYPE_IDENTIFIERS_MATCH(): rcutils_snprintf() failed"; \
88  memmove(__msg, error_msg, sizeof(error_msg)); \
89  } \
90  RMW_SET_ERROR_MSG(__msg); \
91  OnFailure; \
92  } \
93  }
94 #else // RMW_AVOID_MEMORY_ALLOCATION
95 #define RMW_CHECK_TYPE_IDENTIFIERS_MATCH(ElementName, ElementTypeID, ExpectedTypeID, OnFailure) \
96  { \
97  if (ElementTypeID != ExpectedTypeID) { \
98  int __bytes_that_would_have_been_written = rcutils_snprintf( \
99  NULL, 0, \
100  #ElementName " implementation '%s'(%p) does not match rmw implementation '%s'(%p)", \
101  ElementTypeID, reinterpret_cast<const void *>(ElementTypeID), \
102  ExpectedTypeID, reinterpret_cast<const void *>(ExpectedTypeID)); \
103  if (__bytes_that_would_have_been_written < 0) { \
104  RMW_SET_ERROR_MSG( \
105  "RMW_CHECK_TYPE_IDENTIFIERS_MATCH(): rcutils_snprintf(NULL, 0, ...) failed"); \
106  OnFailure; \
107  } else { \
108  char * __msg = \
109  reinterpret_cast<char *>(rmw_allocate(__bytes_that_would_have_been_written + 1)); \
110  if (NULL == __msg) { \
111  RMW_SET_ERROR_MSG( \
112  "RMW_CHECK_TYPE_IDENTIFIERS_MATCH(): rmw_allocate() failed"); \
113  } else { \
114  int ret = rcutils_snprintf( \
115  __msg, __bytes_that_would_have_been_written + 1, \
116  #ElementName " implementation '%s'(%p) does not match rmw implementation '%s'(%p)", \
117  ElementTypeID, reinterpret_cast<const void *>(ElementTypeID), \
118  ExpectedTypeID, reinterpret_cast<const void *>(ExpectedTypeID)); \
119  if (ret < 0) { \
120  RMW_SET_ERROR_MSG( \
121  "RMW_CHECK_TYPE_IDENTIFIERS_MATCH(): rcutils_snprintf() failed"); \
122  } else { \
123  RMW_SET_ERROR_MSG(__msg); \
124  } \
125  } \
126  rmw_free(__msg); \
127  OnFailure; \
128  } \
129  } \
130  }
131 #endif // RMW_AVOID_MEMORY_ALLOCATION
132 
133 #endif // RMW__IMPL__CPP__MACROS_HPP_