lamppp
Loading...
Searching...
No Matches
assert.hpp
1#pragma once
2
3#include <cassert>
4#include <iostream>
5#include <stdexcept>
6#include <sstream>
7#include "stream.hpp"
8
9#ifdef LMP_ENABLE_CUDA
10#include <cuda_runtime.h>
11#endif
12
13namespace lmp {
14namespace detail {
15
16template<typename Derived>
18 BaseStream() = default;
19public:
20 template<class T>
21 Derived& operator<<(T&& v) {
22 os_ << std::forward<T>(v);
23 return static_cast<Derived&>(*this);
24 }
25protected:
26 std::ostringstream os_;
27friend Derived;
28};
29
30class CheckStream : public BaseStream<CheckStream> {
31public:
32 CheckStream(const char* file, int line, const char* func, const char* expr) {
33 os_ << "Lamppp: Runtime error thrown at " << file << ':' << line
34 << " in " << func << ". CHECK(" << expr << ") failed: ";
35 }
36
37 [[noreturn]] void trigger() const {
38 std::cerr << os_.str() << std::endl;
39 throw std::runtime_error(os_.str());
40 }
41};
42
43#ifdef LMP_DEBUG
44
45class AssertStream : public BaseStream<AssertStream> {
46public:
47 AssertStream(const char* file, int line, const char* func, const char* expr) {
48 os_ << "Lamppp: Internal assertion failure at " << file << ':' << line
49 << " in " << func << ". ASSERT(" << expr << ") failed: ";
50 }
51
52 [[noreturn]] void trigger() const {
53 std::cerr << os_.str() << std::endl;
54 std::terminate();
55 }
56};
57
58#ifdef LMP_ENABLE_CUDA
59class CudaAssertStream : public BaseStream<CudaAssertStream> {
60public:
61 CudaAssertStream(const char* file, int line, const char* func, cudaError_t err) {
62 os_ << "Lamppp: CUDA error at " << file << ':' << line
63 << " in " << func << ". Error: " << cudaGetErrorString(err) << ". ";
64 }
65
66 [[noreturn]] void trigger() const {
67 std::cerr << os_.str() << std::endl;
68 std::terminate();
69 }
70};
71#endif
72
73#endif
74
75struct Voidify {
76 template<class T>
77 void operator&(T&& stream) const {
78 stream.trigger();
79 }
80};
81
82} // namespace detail
83} // namespace lmp
84
85#define LMP_CHECK(cond) \
86 (cond) ? (void)0 : ::lmp::detail::Voidify() & ::lmp::detail::CheckStream(__FILE__, __LINE__, __func__, #cond)
87
88#ifdef LMP_DEBUG
89
90#define LMP_INTERNAL_ASSERT(cond) \
91 (cond) ? (void)0 : ::lmp::detail::Voidify() & ::lmp::detail::AssertStream(__FILE__, __LINE__, __func__, #cond)
92
93
94#ifdef LMP_ENABLE_CUDA
95
96namespace lmp::detail {
97
98inline cudaError_t& cuda_assert_last_error() {
99 static thread_local cudaError_t last{};
100 return last;
101}
102
103template<class F>
104inline bool cuda_assert_once(F&& f) {
105 cuda_assert_last_error() = f();
106 return cuda_assert_last_error() != cudaSuccess;
107}
108
109}
110
111#define LMP_CUDA_INTERNAL_ASSERT(call) \
112 if (const cudaError_t LMP_CUDA_ERROR = (call); LMP_CUDA_ERROR == cudaSuccess) \
113 ; \
114 else \
115 ::lmp::detail::Voidify() & \
116 ::lmp::detail::CudaAssertStream(__FILE__, __LINE__, __func__, \
117 LMP_CUDA_ERROR)
118
119#define LMP_CUDA_CHECK(call) \
120 if (const cudaError_t LMP_CUDA_ERROR = (call); LMP_CUDA_ERROR == cudaSuccess) \
121 ; \
122 else \
123 ::lmp::detail::Voidify() & \
124 ::lmp::detail::CudaAssertStream(__FILE__, __LINE__, __func__, \
125 LMP_CUDA_ERROR)
126#endif
127
128
129#define LMP_PRINT(fmt, ...) \
130 fprintf(stderr, "[%s:%d] %s: " fmt "\n", __FILE__, __LINE__, __func__, \
131 ##__VA_ARGS__)
132
133#else
134
135namespace lmp::detail {
137 template<typename T> NullStream& operator<<(T&&) { return *this; }
138 void trigger() const {}
139};
140
141}
142#define LMP_INTERNAL_ASSERT(cond) \
143 true ? (void)0 : ::lmp::detail::Voidify() & ::lmp::detail::NullStream()
144#define LMP_CUDA_INTERNAL_ASSERT(call) \
145 true ? (void)0 : ::lmp::detail::Voidify() & ::lmp::detail::NullStream()
146#define LMP_CUDA_CHECK(call) \
147 (call) ? (void)0 : ::lmp::detail::Voidify() & ::lmp::detail::NullStream()
148
149#endif
Definition assert.hpp:17
Definition assert.hpp:30
Definition assert.hpp:136
Definition assert.hpp:75