summaryrefslogtreecommitdiff
path: root/src/common/scope_exit.h
diff options
context:
space:
mode:
authorGravatar FearlessTobi2024-02-19 16:00:46 +0100
committerGravatar FearlessTobi2024-02-19 16:00:46 +0100
commit310c1f50beb77fc5c6f9075029973161d4e51a4a (patch)
tree43a5699123e4930560fc5016faac7efb15b63f4e /src/common/scope_exit.h
parentcore/CMakeLists: Sort alphabetically (diff)
downloadyuzu-310c1f50beb77fc5c6f9075029973161d4e51a4a.tar.gz
yuzu-310c1f50beb77fc5c6f9075029973161d4e51a4a.tar.xz
yuzu-310c1f50beb77fc5c6f9075029973161d4e51a4a.zip
scope_exit: Make constexpr
Allows the use of the macro in constexpr-contexts. Also avoids some potential problems when nesting braces inside it.
Diffstat (limited to '')
-rw-r--r--src/common/scope_exit.h66
1 files changed, 46 insertions, 20 deletions
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 @@
7#include "common/common_funcs.h" 7#include "common/common_funcs.h"
8 8
9namespace detail { 9namespace detail {
10template <typename Func> 10template <class F>
11struct ScopeExitHelper { 11class ScopeGuard {
12 explicit ScopeExitHelper(Func&& func_) : func(std::move(func_)) {} 12 YUZU_NON_COPYABLE(ScopeGuard);
13 ~ScopeExitHelper() { 13
14private:
15 F f;
16 bool active;
17
18public:
19 constexpr ScopeGuard(F f_) : f(std::move(f_)), active(true) {}
20 constexpr ~ScopeGuard() {
14 if (active) { 21 if (active) {
15 func(); 22 f();
16 } 23 }
17 } 24 }
18 25 constexpr void Cancel() {
19 void Cancel() {
20 active = false; 26 active = false;
21 } 27 }
22 28
23 Func func; 29 constexpr ScopeGuard(ScopeGuard&& rhs) : f(std::move(rhs.f)), active(rhs.active) {
24 bool active{true}; 30 rhs.Cancel();
31 }
32
33 ScopeGuard& operator=(ScopeGuard&& rhs) = delete;
25}; 34};
26 35
27template <typename Func> 36template <class F>
28ScopeExitHelper<Func> ScopeExit(Func&& func) { 37constexpr ScopeGuard<F> MakeScopeGuard(F f) {
29 return ScopeExitHelper<Func>(std::forward<Func>(func)); 38 return ScopeGuard<F>(std::move(f));
30} 39}
40
41enum class ScopeGuardOnExit {};
42
43template <typename F>
44constexpr ScopeGuard<F> operator+(ScopeGuardOnExit, F&& f) {
45 return ScopeGuard<F>(std::forward<F>(f));
46}
47
31} // namespace detail 48} // namespace detail
32 49
50#define CONCATENATE_IMPL(s1, s2) s1##s2
51#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2)
52
53#ifdef __COUNTER__
54#define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __COUNTER__)
55#else
56#define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __LINE__)
57#endif
58
59/**
60 * This macro is similar to SCOPE_EXIT, except the object is caller managed. This is intended to be
61 * used when the caller might want to cancel the ScopeExit.
62 */
63#define SCOPE_GUARD detail::ScopeGuardOnExit() + [&]()
64
33/** 65/**
34 * This macro allows you to conveniently specify a block of code that will run on scope exit. Handy 66 * This macro allows you to conveniently specify a block of code that will run on scope exit. Handy
35 * for doing ad-hoc clean-up tasks in a function with multiple returns. 67 * for doing ad-hoc clean-up tasks in a function with multiple returns.
@@ -38,7 +70,7 @@ ScopeExitHelper<Func> ScopeExit(Func&& func) {
38 * \code 70 * \code
39 * const int saved_val = g_foo; 71 * const int saved_val = g_foo;
40 * g_foo = 55; 72 * g_foo = 55;
41 * SCOPE_EXIT({ g_foo = saved_val; }); 73 * SCOPE_EXIT{ g_foo = saved_val; };
42 * 74 *
43 * if (Bar()) { 75 * if (Bar()) {
44 * return 0; 76 * return 0;
@@ -47,10 +79,4 @@ ScopeExitHelper<Func> ScopeExit(Func&& func) {
47 * } 79 * }
48 * \endcode 80 * \endcode
49 */ 81 */
50#define SCOPE_EXIT(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body) 82#define SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE_) = SCOPE_GUARD
51
52/**
53 * This macro is similar to SCOPE_EXIT, except the object is caller managed. This is intended to be
54 * used when the caller might want to cancel the ScopeExit.
55 */
56#define SCOPE_GUARD(body) detail::ScopeExit([&]() body)