2022-05-15 02:06:02 +02:00
|
|
|
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
|
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2014-11-02 17:34:14 -02:00
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
2015-01-20 17:16:47 -08:00
|
|
|
#include <utility>
|
2016-09-18 09:38:01 +09:00
|
|
|
#include "common/common_funcs.h"
|
2015-01-11 13:32:31 -02:00
|
|
|
|
2014-11-02 17:34:14 -02:00
|
|
|
namespace detail {
|
2024-02-19 16:00:46 +01:00
|
|
|
template <class F>
|
|
|
|
|
class ScopeGuard {
|
|
|
|
|
YUZU_NON_COPYABLE(ScopeGuard);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
F f;
|
|
|
|
|
bool active;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
constexpr ScopeGuard(F f_) : f(std::move(f_)), active(true) {}
|
|
|
|
|
constexpr ~ScopeGuard() {
|
2020-03-31 15:16:07 -04:00
|
|
|
if (active) {
|
2024-02-19 16:00:46 +01:00
|
|
|
f();
|
2020-03-31 15:16:07 -04:00
|
|
|
}
|
|
|
|
|
}
|
2024-02-19 16:00:46 +01:00
|
|
|
constexpr void Cancel() {
|
2020-03-31 15:16:07 -04:00
|
|
|
active = false;
|
2016-09-18 09:38:01 +09:00
|
|
|
}
|
2014-11-02 17:34:14 -02:00
|
|
|
|
2024-02-19 16:00:46 +01:00
|
|
|
constexpr ScopeGuard(ScopeGuard&& rhs) : f(std::move(rhs.f)), active(rhs.active) {
|
|
|
|
|
rhs.Cancel();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ScopeGuard& operator=(ScopeGuard&& rhs) = delete;
|
2016-09-18 09:38:01 +09:00
|
|
|
};
|
2014-11-02 17:34:14 -02:00
|
|
|
|
2024-02-19 16:00:46 +01:00
|
|
|
template <class F>
|
|
|
|
|
constexpr ScopeGuard<F> MakeScopeGuard(F f) {
|
|
|
|
|
return ScopeGuard<F>(std::move(f));
|
2016-09-18 09:38:01 +09:00
|
|
|
}
|
2024-02-19 16:00:46 +01:00
|
|
|
|
|
|
|
|
enum class ScopeGuardOnExit {};
|
|
|
|
|
|
|
|
|
|
template <typename F>
|
|
|
|
|
constexpr ScopeGuard<F> operator+(ScopeGuardOnExit, F&& f) {
|
|
|
|
|
return ScopeGuard<F>(std::forward<F>(f));
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-20 00:48:02 -07:00
|
|
|
} // namespace detail
|
2014-11-02 17:34:14 -02:00
|
|
|
|
2024-02-19 16:00:46 +01:00
|
|
|
#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() + [&]()
|
|
|
|
|
|
2014-11-02 17:34:14 -02:00
|
|
|
/**
|
|
|
|
|
* 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;
|
2024-02-19 16:00:46 +01:00
|
|
|
* SCOPE_EXIT{ g_foo = saved_val; };
|
2014-11-02 17:34:14 -02:00
|
|
|
*
|
|
|
|
|
* if (Bar()) {
|
|
|
|
|
* return 0;
|
|
|
|
|
* } else {
|
|
|
|
|
* return 20;
|
|
|
|
|
* }
|
|
|
|
|
* \endcode
|
|
|
|
|
*/
|
2024-02-19 16:00:46 +01:00
|
|
|
#define SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE_) = SCOPE_GUARD
|