2018-01-28 17:57:02 +00:00
|
|
|
/* This file is part of the dynarmic project.
|
|
|
|
* Copyright (c) 2018 MerryMage
|
|
|
|
* This software may be used and distributed according to the terms of the GNU
|
|
|
|
* General Public License version 2 or any later version.
|
|
|
|
*/
|
2016-07-04 07:56:41 +01:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2018-01-28 17:57:02 +00:00
|
|
|
#include <exception>
|
|
|
|
#include <type_traits>
|
2016-07-04 07:56:41 +01:00
|
|
|
#include <utility>
|
|
|
|
|
2018-01-28 17:57:02 +00:00
|
|
|
#include "common/macro_util.h"
|
|
|
|
|
|
|
|
namespace Dynarmic::detail {
|
|
|
|
|
|
|
|
struct ScopeExitTag {};
|
|
|
|
struct ScopeFailTag {};
|
|
|
|
struct ScopeSuccessTag {};
|
|
|
|
|
|
|
|
template <typename Function>
|
|
|
|
class ScopeExit final {
|
|
|
|
public:
|
|
|
|
explicit ScopeExit(Function&& fn) : function(std::move(fn)) {}
|
|
|
|
~ScopeExit() noexcept {
|
|
|
|
function();
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
Function function;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename Function>
|
|
|
|
class ScopeFail final {
|
|
|
|
public:
|
|
|
|
explicit ScopeFail(Function&& fn) : function(std::move(fn)), exception_count(std::uncaught_exceptions()) {}
|
|
|
|
~ScopeFail() noexcept {
|
|
|
|
if (std::uncaught_exceptions() > exception_count) {
|
|
|
|
function();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
Function function;
|
|
|
|
int exception_count;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename Function>
|
|
|
|
class ScopeSuccess final {
|
|
|
|
public:
|
|
|
|
explicit ScopeSuccess(Function&& fn) : function(std::move(fn)), exception_count(std::uncaught_exceptions()) {}
|
|
|
|
~ScopeSuccess() {
|
|
|
|
if (std::uncaught_exceptions() <= exception_count) {
|
|
|
|
function();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
Function function;
|
|
|
|
int exception_count;
|
|
|
|
};
|
2016-07-04 07:56:41 +01:00
|
|
|
|
2018-01-28 17:57:02 +00:00
|
|
|
// We use ->* here as it has the highest precedence of the operators we can use.
|
2016-07-04 07:56:41 +01:00
|
|
|
|
2018-01-28 17:57:02 +00:00
|
|
|
template <typename Function>
|
|
|
|
auto operator->*(ScopeExitTag, Function&& function) {
|
|
|
|
return ScopeExit<std::decay_t<Function>>{std::forward<Function>(function)};
|
2016-07-04 07:56:41 +01:00
|
|
|
}
|
|
|
|
|
2018-01-28 17:57:02 +00:00
|
|
|
template <typename Function>
|
|
|
|
auto operator->*(ScopeFailTag, Function&& function) {
|
|
|
|
return ScopeFail<std::decay_t<Function>>{std::forward<Function>(function)};
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Function>
|
|
|
|
auto operator->*(ScopeSuccessTag, Function&& function) {
|
|
|
|
return ScopeSuccess<std::decay_t<Function>>{std::forward<Function>(function)};
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Dynarmic::detail
|
|
|
|
|
|
|
|
#define SCOPE_EXIT auto ANONYMOUS_VARIABLE(_SCOPE_EXIT_) = ::Dynarmic::detail::ScopeExitTag{} ->* [&]() noexcept
|
|
|
|
#define SCOPE_FAIL auto ANONYMOUS_VARIABLE(_SCOPE_FAIL_) = ::Dynarmic::detail::ScopeFailTag{} ->* [&]() noexcept
|
|
|
|
#define SCOPE_SUCCESS auto ANONYMOUS_VARIABLE(_SCOPE_FAIL_) = ::Dynarmic::detail::ScopeSuccessTag{} ->* [&]()
|