scope_exit.h 1.3 KB

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