/* 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. */ #pragma once #include #include #include #include "common/macro_util.h" namespace Dynarmic::detail { struct ScopeExitTag {}; struct ScopeFailTag {}; struct ScopeSuccessTag {}; template class ScopeExit final { public: explicit ScopeExit(Function&& fn) : function(std::move(fn)) {} ~ScopeExit() noexcept { function(); } private: Function function; }; template 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 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; }; // We use ->* here as it has the highest precedence of the operators we can use. template auto operator->*(ScopeExitTag, Function&& function) { return ScopeExit>{std::forward(function)}; } template auto operator->*(ScopeFailTag, Function&& function) { return ScopeFail>{std::forward(function)}; } template auto operator->*(ScopeSuccessTag, Function&& function) { return ScopeSuccess>{std::forward(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{} ->* [&]()