rmw  master
C API providing a middleware abstraction layer which is used to implement the rest of ROS.
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_