diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index ab005f27..68755060 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -16,6 +16,7 @@ set(HEADERS logging/log.h memory_util.h mp.h + scope_exit.h string_util.h x64/abi.h x64/cpu_detect.h diff --git a/src/common/scope_exit.h b/src/common/scope_exit.h new file mode 100644 index 00000000..45974a68 --- /dev/null +++ b/src/common/scope_exit.h @@ -0,0 +1,42 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +namespace detail { + template + struct ScopeExitHelper { + explicit ScopeExitHelper(Func&& func) : func(std::move(func)) {} + ~ScopeExitHelper() { func(); } + + Func func; + }; + + template + ScopeExitHelper ScopeExit(Func&& func) { return ScopeExitHelper(std::move(func)); } +} + +#define CONCAT2(x, y) DO_CONCAT2(x, y) +#define DO_CONCAT2(x, y) x ## y + +/** + * 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(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body)