From 08b09e175f6980d1a25eb043ca97b6dbc9dc52d4 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sat, 30 Nov 2024 15:59:20 +0200 Subject: [PATCH] Add ScopeExit --- third_party/host_memory/host_memory.cpp | 2 +- .../include/host_memory/scope_exit.h | 78 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 third_party/host_memory/include/host_memory/scope_exit.h diff --git a/third_party/host_memory/host_memory.cpp b/third_party/host_memory/host_memory.cpp index aad8b166..e1fe84b6 100644 --- a/third_party/host_memory/host_memory.cpp +++ b/third_party/host_memory/host_memory.cpp @@ -30,7 +30,7 @@ #include -#include "common/scope_exit.h" +#include #ifndef MAP_NORESERVE diff --git a/third_party/host_memory/include/host_memory/scope_exit.h b/third_party/host_memory/include/host_memory/scope_exit.h new file mode 100644 index 00000000..771ad2ef --- /dev/null +++ b/third_party/host_memory/include/host_memory/scope_exit.h @@ -0,0 +1,78 @@ +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +namespace detail { + template + class ScopeGuard { + ScopeGuard(const ScopeGuard&) = delete; + ScopeGuard& operator=(const ScopeGuard&) = delete; + + private: + F f; + bool active; + + public: + constexpr ScopeGuard(F f_) : f(std::move(f_)), active(true) {} + constexpr ~ScopeGuard() { + if (active) { + f(); + } + } + + constexpr void Cancel() { active = false; } + constexpr ScopeGuard(ScopeGuard&& rhs) : f(std::move(rhs.f)), active(rhs.active) { rhs.Cancel(); } + + ScopeGuard& operator=(ScopeGuard&& rhs) = delete; + }; + + template + constexpr ScopeGuard MakeScopeGuard(F f) { + return ScopeGuard(std::move(f)); + } + + enum class ScopeGuardOnExit {}; + + template + constexpr ScopeGuard operator+(ScopeGuardOnExit, F&& f) { + return ScopeGuard(std::forward(f)); + } + +} // namespace detail + +#define CONCATENATE_IMPL(s1, s2) s1##s2 +#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2) + +#ifdef __COUNTER__ +#define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __COUNTER__) +#else +#define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __LINE__) +#endif + +/** + * This macro is similar to SCOPE_EXIT, except the object is caller managed. This is intended to be + * used when the caller might want to cancel the ScopeExit. + */ +#define SCOPE_GUARD detail::ScopeGuardOnExit() + [&]() + +/** + * This macro allows you to conveniently specify a block of code that will run on scope exit. Handy + * for doing ad-hoc clean-up tasks in a function with multiple returns. + * + * Example usage: + * \code + * const int saved_val = g_foo; + * g_foo = 55; + * SCOPE_EXIT{ g_foo = saved_val; }; + * + * if (Bar()) { + * return 0; + * } else { + * return 20; + * } + * \endcode + */ +#define SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE_) = SCOPE_GUARD