error.hpp
1 
6 #pragma once
7 
8 #include <stdexcept> // NOLINT(unused-includes)
9 
10 #include <rapidsmpf/utils.hpp>
11 
12 namespace rapidsmpf {
13 
20 struct cuda_error : public std::runtime_error {
21  using std::runtime_error::runtime_error;
22 };
23 
30 class bad_alloc : public std::bad_alloc {
31  public:
37  bad_alloc(const char* msg)
38  : _what{std::string{std::bad_alloc::what()} + ": " + msg} {}
39 
45  bad_alloc(std::string const& msg) : bad_alloc{msg.c_str()} {}
46 
52  [[nodiscard]] const char* what() const noexcept override {
53  return _what.c_str();
54  }
55 
56  private:
57  std::string _what;
58 };
59 
67 class out_of_memory : public bad_alloc {
68  public:
74  out_of_memory(const char* msg) : bad_alloc{std::string{"out_of_memory: "} + msg} {}
75 
81  out_of_memory(std::string const& msg) : out_of_memory{msg.c_str()} {}
82 };
83 
109 #define RAPIDSMPF_EXPECTS(...) \
110  GET_RAPIDSMPF_EXPECTS_MACRO(__VA_ARGS__, RAPIDSMPF_EXPECTS_3, RAPIDSMPF_EXPECTS_2) \
111  (__VA_ARGS__)
112 
113 #define GET_RAPIDSMPF_EXPECTS_MACRO(_1, _2, _3, NAME, ...) NAME
114 
115 #define RAPIDSMPF_EXPECTS_3(_condition, _reason, _exception_type) \
116  do { \
117  static_assert(std::is_base_of_v<std::exception, _exception_type>); \
118  (_condition) ? static_cast<void>(0) \
119  : throw _exception_type /*NOLINT(bugprone-macro-parentheses)*/ \
120  {"RAPIDSMPF failure at: " __FILE__ \
121  ":" RAPIDSMPF_STRINGIFY(__LINE__) ": " _reason}; \
122  } while (0)
123 
124 #define RAPIDSMPF_EXPECTS_2(_condition, _reason) \
125  RAPIDSMPF_EXPECTS_3(_condition, _reason, std::logic_error)
126 
127 
148 #define RAPIDSMPF_FAIL(...) \
149  GET_RAPIDSMPF_FAIL_MACRO(__VA_ARGS__, RAPIDSMPF_FAIL_2, RAPIDSMPF_FAIL_1) \
150  (__VA_ARGS__)
151 
152 #define GET_RAPIDSMPF_FAIL_MACRO(_1, _2, NAME, ...) NAME
153 
154 #define RAPIDSMPF_FAIL_2(_what, _exception_type) \
155  /*NOLINTNEXTLINE(bugprone-macro-parentheses)*/ \
156  throw _exception_type { \
157  "RAPIDSMPF failure at:" __FILE__ ":" RAPIDSMPF_STRINGIFY(__LINE__) ": " _what \
158  }
159 
160 #define RAPIDSMPF_FAIL_1(_what) RAPIDSMPF_FAIL_2(_what, std::logic_error)
161 
183 #define RAPIDSMPF_CUDA_TRY(...) \
184  GET_RAPIDSMPF_CUDA_TRY_MACRO( \
185  __VA_ARGS__, RAPIDSMPF_CUDA_TRY_2, RAPIDSMPF_CUDA_TRY_1 \
186  ) \
187  (__VA_ARGS__)
188 #define GET_RAPIDSMPF_CUDA_TRY_MACRO(_1, _2, NAME, ...) NAME
189 #define RAPIDSMPF_CUDA_TRY_2(_call, _exception_type) \
190  do { \
191  cudaError_t const error = (_call); \
192  if (cudaSuccess != error) { \
193  cudaGetLastError(); \
194  /*NOLINTNEXTLINE(bugprone-macro-parentheses)*/ \
195  throw _exception_type{ \
196  std::string{"CUDA error at: "} + __FILE__ + ":" \
197  + RAPIDSMPF_STRINGIFY(__LINE__) + ": " + cudaGetErrorName(error) + " " \
198  + cudaGetErrorString(error) \
199  }; \
200  } \
201  } while (0)
202 #define RAPIDSMPF_CUDA_TRY_1(_call) RAPIDSMPF_CUDA_TRY_2(_call, rapidsmpf::cuda_error)
203 
219 #define RAPIDSMPF_CUDA_TRY_ALLOC(...) \
220  GET_RAPIDSMPF_CUDA_TRY_ALLOC_MACRO( \
221  __VA_ARGS__, RAPIDSMPF_CUDA_TRY_ALLOC_2, RAPIDSMPF_CUDA_TRY_ALLOC_1 \
222  ) \
223  (__VA_ARGS__)
224 #define GET_RAPIDSMPF_CUDA_TRY_ALLOC_MACRO(_1, _2, NAME, ...) NAME
225 
226 #define RAPIDSMPF_CUDA_TRY_ALLOC_2(_call, num_bytes) \
227  do { \
228  cudaError_t const error = (_call); \
229  if (cudaSuccess != error) { \
230  cudaGetLastError(); \
231  auto const msg = std::string{"CUDA error (failed to allocate "} \
232  + std::to_string(num_bytes) + " bytes) at: " + __FILE__ \
233  + ":" + RAPIDSMPF_STRINGIFY(__LINE__) + ": " \
234  + cudaGetErrorName(error) + " " \
235  + cudaGetErrorString(error); \
236  if (cudaErrorMemoryAllocation == error) { \
237  throw rapidsmpf::out_of_memory{msg}; \
238  } \
239  throw rapidsmpf::bad_alloc{msg}; \
240  } \
241  } while (0)
242 
243 #define RAPIDSMPF_CUDA_TRY_ALLOC_1(_call) \
244  do { \
245  cudaError_t const error = (_call); \
246  if (cudaSuccess != error) { \
247  cudaGetLastError(); \
248  auto const msg = std::string{"CUDA error at: "} + __FILE__ + ":" \
249  + RAPIDSMPF_STRINGIFY(__LINE__) + ": " \
250  + cudaGetErrorName(error) + " " \
251  + cudaGetErrorString(error); \
252  if (cudaErrorMemoryAllocation == error) { \
253  throw rapidsmpf::out_of_memory{msg}; \
254  } \
255  throw rapidsmpf::bad_alloc{msg}; \
256  } \
257  } while (0)
258 
284 #ifdef NDEBUG
285 #define RAPIDSMPF_ASSERT_CUDA_SUCCESS(_call) \
286  do { \
287  (_call); \
288  } while (0);
289 #else
290 #define RAPIDSMPF_ASSERT_CUDA_SUCCESS(_call) \
291  do { \
292  cudaError_t const status__ = (_call); \
293  if (status__ != cudaSuccess) { \
294  std::cerr << "CUDA Error detected. " << cudaGetErrorName(status__) << " " \
295  << cudaGetErrorString(status__) << std::endl; \
296  } \
297  /* NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay) */ \
298  assert(status__ == cudaSuccess); \
299  } while (0)
300 #endif
301 
302 } // namespace rapidsmpf
Exception thrown when an RapidsMPF allocation fails.
Definition: error.hpp:30
const char * what() const noexcept override
Returns the explanatory string.
Definition: error.hpp:52
bad_alloc(std::string const &msg)
Constructs a bad_alloc with the error message.
Definition: error.hpp:45
bad_alloc(const char *msg)
Constructs a bad_alloc with the error message.
Definition: error.hpp:37
Exception thrown when RapidsMPF runs out of memory.
Definition: error.hpp:67
out_of_memory(std::string const &msg)
Constructs an out_of_memory with the error message.
Definition: error.hpp:81
out_of_memory(const char *msg)
Constructs an out_of_memory with the error message.
Definition: error.hpp:74
Exception thrown when a CUDA error is encountered.
Definition: error.hpp:20