28#define MOCHI_ASSERT_ON_FAILURE(file, line, conditionStr, ...) \
29 if (::superdex::OnAssertionFailure(file, line, conditionStr __VA_OPT__(, )##__VA_ARGS__)) { \
30 MOCHI_DEBUG_BREAK(); \
33#define MOCHI_ASSERT_ON_FAILURE(file, line, conditionStr, ...) \
34 if (::superdex::OnAssertionFailure(file, line, conditionStr, ##__VA_ARGS__)) { \
35 MOCHI_DEBUG_BREAK(); \
44#define MOCHI_ASSERT_ON_FAILURE(file, line, conditionStr, ...) \
45 printf("%s(%d): Assertion Failure! Expected (%s)\n", file, line, conditionStr); \
46 printf("" __VA_ARGS__); \
50#error Expected MOCHI_ARCH_CPU or MOCHI_ARCH_GPU
51#define MOCHI_ASSERT_ON_FAILURE
56#define MOCHI_ASSERT_IMPL(condition, ...) \
60 MOCHI_ASSERT_ON_FAILURE(__FILE__, __LINE__, #condition __VA_OPT__(, )##__VA_ARGS__); \
63#define MOCHI_ASSERT_IMPL(condition, ...) \
67 MOCHI_ASSERT_ON_FAILURE(__FILE__, __LINE__, #condition, ##__VA_ARGS__); \
73namespace assert_impl {
76inline std::recursive_mutex& GetAssertMutexRef() {
77 static std::recursive_mutex s_assertMutex;
84inline int& GetAssertCallDepthRef() {
85 static int s_assertCallDepth = 0;
86 return s_assertCallDepth;
91DefaultAssertHandler(
char const* condition,
char const* message,
char const* file,
int line) {
94 "*****************************************************************************\n"
95 "MOCHI ASSERTION FAILURE:\n"
99 "*****************************************************************************\n",
112 bool const triggerDebugBreak =
true;
114 return triggerDebugBreak;
119template <
class DstPtrT,
class SrcT>
121 static_assert(std::is_pointer_v<DstPtrT>,
"Invalid cast. Expected a pointer type.");
122 MOCHI_ASSERT(
dynamic_cast<DstPtrT
>(ptr) ==
static_cast<DstPtrT
>(ptr),
"Invalid cast");
123 return static_cast<DstPtrT
>(ptr);
125template <
class DstRefT,
class SrcT>
127 static_assert(std::is_reference_v<DstRefT>,
"Invalid cast. Expected a reference type.");
129 dynamic_cast<std::remove_reference_t<DstRefT>*
>(&ref) ==
130 static_cast<std::remove_reference_t<DstRefT>*
>(&ref),
132 return static_cast<DstRefT
>(ref);
137inline OnAssertFn GetAssertionFailureCallback() {
139 std::lock_guard<std::recursive_mutex> lock(assert_impl::GetAssertMutexRef());
140 auto& fn = assert_impl::GetOnAssertFnRef();
141 return fn ? fn :
OnAssertFn{assert_impl::DefaultAssertHandler};
143 return OnAssertFn{assert_impl::DefaultAssertHandler};
147inline void SetAssertionFailureCallback([[maybe_unused]]
OnAssertFn fn) {
149 std::lock_guard<std::recursive_mutex> lock(assert_impl::GetAssertMutexRef());
150 assert_impl::GetOnAssertFnRef() = fn ? fn :
OnAssertFn{assert_impl::DefaultAssertHandler};
155MOCHI_NO_INLINE
inline bool
156OnAssertionFailure(
char const* file,
int line,
char const* condition,
char const* msg) {
158 std::lock_guard<std::recursive_mutex> lock(assert_impl::GetAssertMutexRef());
159 int& callDepth = assert_impl::GetAssertCallDepthRef();
160 if (callDepth != 0) {
165 bool shouldBreak = GetAssertionFailureCallback()(condition, msg, file, line);
169 return GetAssertionFailureCallback()(condition, msg, file, line);
174template <
typename... Args>
175MOCHI_NO_INLINE
bool OnAssertionFailure(
178 char const* condition,
181 return OnAssertionFailure(file, line, condition,
Format(fmt, args...).c_str());
185MOCHI_NO_INLINE
inline bool OnAssertionFailure(
char const* file,
int line,
char const* condition) {
186 return OnAssertionFailure(file, line, condition,
"");
#define MOCHI_ASSERT(condition_without_side_effects,...)
#define MOCHI_LOG_ERROR(...)
std::function< bool(char const *condition, char const *message, char const *file, int line)> OnAssertFn
Callback invoked when an assertion fails.