-
-
Save bruxisma/7428489ef96d773e138bfae4a3cec1ec to your computer and use it in GitHub Desktop.
im gay
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Jumpman { | |
using default_throw_t = void(*)(void*); | |
default_throw_t default_throw; | |
void* default_throw_arg; | |
std::exception_ptr current_exception; | |
std::jmp_buf jmp; | |
bool jump_active; | |
[[noreturn]] void rethrow_exception(); | |
public: | |
Jumpman(default_throw_t default_throw, void* default_throw_arg) noexcept : | |
default_throw { default_throw }, | |
default_throw_arg { default_throw_arg }, | |
jump_active { } | |
{ } | |
[[noreturn]] void execute_jump(); | |
void store_exception(); | |
template <class T, class ...Args> | |
decltype(auto) call(T&& func, Args &&...args) { | |
if (setjmp(this->jmp)) { | |
this->jump_active = false; | |
this->rethrow_exception(); | |
} | |
this->current_exception = nullptr; | |
this->jump_active = true; | |
// We can't use a scope_exit because if an exception is thrown, the entire | |
// program unwinds. Otherwise this would be simpler at the end. | |
auto cleanup = [&] { | |
this->jump_active = false; | |
if (this->current_exception) { this->rethrow_exception(); } | |
}; | |
if constexpr (std::is_void_v<std::invoke_result_t<T, Args...>>) { | |
std::invoke(std::forward<T>(func), std::forward<Args>(args)...); | |
cleanup(); | |
} else { | |
decltype(auto) result = std::invoke(std::forward<T>(func), std::forward<Args>(args)...); | |
cleanup(); | |
return std::forward<decltype(result)>(result); | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment