scope_exit.h 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. // SPDX-FileCopyrightText: 2014 Citra Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <utility>
  5. #include "common/common_funcs.h"
  6. namespace detail {
  7. template <typename Func>
  8. struct ScopeExitHelper {
  9. explicit ScopeExitHelper(Func&& func_) : func(std::move(func_)) {}
  10. ~ScopeExitHelper() {
  11. if (active) {
  12. func();
  13. }
  14. }
  15. void Cancel() {
  16. active = false;
  17. }
  18. Func func;
  19. bool active{true};
  20. };
  21. template <typename Func>
  22. ScopeExitHelper<Func> ScopeExit(Func&& func) {
  23. return ScopeExitHelper<Func>(std::forward<Func>(func));
  24. }
  25. } // namespace detail
  26. /**
  27. * This macro allows you to conveniently specify a block of code that will run on scope exit. Handy
  28. * for doing ad-hoc clean-up tasks in a function with multiple returns.
  29. *
  30. * Example usage:
  31. * \code
  32. * const int saved_val = g_foo;
  33. * g_foo = 55;
  34. * SCOPE_EXIT({ g_foo = saved_val; });
  35. *
  36. * if (Bar()) {
  37. * return 0;
  38. * } else {
  39. * return 20;
  40. * }
  41. * \endcode
  42. */
  43. #define SCOPE_EXIT(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body)
  44. /**
  45. * This macro is similar to SCOPE_EXIT, except the object is caller managed. This is intended to be
  46. * used when the caller might want to cancel the ScopeExit.
  47. */
  48. #define SCOPE_GUARD(body) detail::ScopeExit([&]() body)