Skip to content

Instantly share code, notes, and snippets.

@bruxisma
Created August 16, 2018 13:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bruxisma/7428489ef96d773e138bfae4a3cec1ec to your computer and use it in GitHub Desktop.
Save bruxisma/7428489ef96d773e138bfae4a3cec1ec to your computer and use it in GitHub Desktop.
im gay
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