From 310c1f50beb77fc5c6f9075029973161d4e51a4a Mon Sep 17 00:00:00 2001 From: FearlessTobi Date: Mon, 19 Feb 2024 16:00:46 +0100 Subject: scope_exit: Make constexpr Allows the use of the macro in constexpr-contexts. Also avoids some potential problems when nesting braces inside it. --- src/common/demangle.cpp | 4 ++- src/common/host_memory.cpp | 4 +-- src/common/page_table.cpp | 4 +-- src/common/scope_exit.h | 66 ++++++++++++++++++++++++++++++++-------------- 4 files changed, 53 insertions(+), 25 deletions(-) (limited to 'src/common') diff --git a/src/common/demangle.cpp b/src/common/demangle.cpp index 6e117cb41..b2c9d126a 100644 --- a/src/common/demangle.cpp +++ b/src/common/demangle.cpp @@ -20,7 +20,9 @@ std::string DemangleSymbol(const std::string& mangled) { } char* demangled = nullptr; - SCOPE_EXIT({ std::free(demangled); }); + SCOPE_EXIT { + std::free(demangled); + }; if (is_itanium(mangled)) { demangled = llvm::itaniumDemangle(mangled.c_str()); diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 860c39e6a..e0b5a6a67 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -430,11 +430,11 @@ public: explicit Impl(size_t backing_size_, size_t virtual_size_) : backing_size{backing_size_}, virtual_size{virtual_size_} { bool good = false; - SCOPE_EXIT({ + SCOPE_EXIT { if (!good) { Release(); } - }); + }; long page_size = sysconf(_SC_PAGESIZE); if (page_size != 0x1000) { diff --git a/src/common/page_table.cpp b/src/common/page_table.cpp index 85dc18c11..3205eb7da 100644 --- a/src/common/page_table.cpp +++ b/src/common/page_table.cpp @@ -24,10 +24,10 @@ bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* c out_entry->block_size = page_size; // Regardless of whether the page was mapped, advance on exit. - SCOPE_EXIT({ + SCOPE_EXIT { context->next_page += 1; context->next_offset += page_size; - }); + }; // Validate that we can read the actual entry. const auto page = context->next_page; diff --git a/src/common/scope_exit.h b/src/common/scope_exit.h index e9c789c88..f3e88cde9 100644 --- a/src/common/scope_exit.h +++ b/src/common/scope_exit.h @@ -7,29 +7,61 @@ #include "common/common_funcs.h" namespace detail { -template -struct ScopeExitHelper { - explicit ScopeExitHelper(Func&& func_) : func(std::move(func_)) {} - ~ScopeExitHelper() { +template +class ScopeGuard { + YUZU_NON_COPYABLE(ScopeGuard); + +private: + F f; + bool active; + +public: + constexpr ScopeGuard(F f_) : f(std::move(f_)), active(true) {} + constexpr ~ScopeGuard() { if (active) { - func(); + f(); } } - - void Cancel() { + constexpr void Cancel() { active = false; } - Func func; - bool active{true}; + constexpr ScopeGuard(ScopeGuard&& rhs) : f(std::move(rhs.f)), active(rhs.active) { + rhs.Cancel(); + } + + ScopeGuard& operator=(ScopeGuard&& rhs) = delete; }; -template -ScopeExitHelper ScopeExit(Func&& func) { - return ScopeExitHelper(std::forward(func)); +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. @@ -38,7 +70,7 @@ ScopeExitHelper ScopeExit(Func&& func) { * \code * const int saved_val = g_foo; * g_foo = 55; - * SCOPE_EXIT({ g_foo = saved_val; }); + * SCOPE_EXIT{ g_foo = saved_val; }; * * if (Bar()) { * return 0; @@ -47,10 +79,4 @@ ScopeExitHelper ScopeExit(Func&& func) { * } * \endcode */ -#define SCOPE_EXIT(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body) - -/** - * 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(body) detail::ScopeExit([&]() body) +#define SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE_) = SCOPE_GUARD -- cgit v1.2.3