scope-guard.hpp 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. /*
  2. * Based on Loki::ScopeGuard
  3. */
  4. #pragma once
  5. #include <utility>
  6. namespace scope_guard_util {
  7. template<typename FunctionType> class ScopeGuard {
  8. public:
  9. void dismiss() noexcept { dismissed_ = true; }
  10. explicit ScopeGuard(const FunctionType &fn) : function_(fn) {}
  11. explicit ScopeGuard(FunctionType &&fn) : function_(std::move(fn)) {}
  12. ScopeGuard(ScopeGuard &&other)
  13. : dismissed_(other.dismissed_),
  14. function_(std::move(other.function_))
  15. {
  16. other.dismissed_ = true;
  17. }
  18. ~ScopeGuard() noexcept
  19. {
  20. if (!dismissed_)
  21. execute();
  22. }
  23. private:
  24. void *operator new(size_t) = delete;
  25. void execute() noexcept { function_(); }
  26. bool dismissed_ = false;
  27. FunctionType function_;
  28. };
  29. template<typename FunctionType>
  30. ScopeGuard<typename std::decay<FunctionType>::type>
  31. make_guard(FunctionType &&fn)
  32. {
  33. return ScopeGuard<typename std::decay<FunctionType>::type>{
  34. std::forward<FunctionType>(fn)};
  35. }
  36. namespace detail {
  37. enum class ScopeGuardOnExit {};
  38. template<typename FunctionType>
  39. ScopeGuard<typename std::decay<FunctionType>::type>
  40. operator+(detail::ScopeGuardOnExit, FunctionType &&fn)
  41. {
  42. return ScopeGuard<typename std::decay<FunctionType>::type>(
  43. std::forward<FunctionType>(fn));
  44. }
  45. }
  46. } // namespace scope_guard_util
  47. #define SCOPE_EXIT_CONCAT2(x, y) x##y
  48. #define SCOPE_EXIT_CONCAT(x, y) SCOPE_EXIT_CONCAT2(x, y)
  49. #define SCOPE_EXIT \
  50. auto SCOPE_EXIT_CONCAT(SCOPE_EXIT_STATE, __LINE__) = \
  51. ::scope_guard_util::detail::ScopeGuardOnExit() + [&]() noexcept