scope_guard.hpp 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. //
  2. // scope_guard.hpp
  3. // memory
  4. //
  5. // Created by Sam Jaffe on 9/24/15.
  6. //
  7. //
  8. #pragma once
  9. #include <functional>
  10. class scope_exit {
  11. public:
  12. template <typename F> scope_exit(F f) : on_exit_(f) {}
  13. scope_exit(scope_exit const &) = delete;
  14. scope_exit &operator=(scope_exit const &) = delete;
  15. scope_exit(scope_exit &&) = default;
  16. scope_exit &operator=(scope_exit &&) = default;
  17. ~scope_exit() noexcept { if (on_exit_) { on_exit_(); } }
  18. void release() { on_exit_ = {}; }
  19. private:
  20. std::function<void()> on_exit_;
  21. };
  22. #if __cplusplus > 201402L
  23. template <bool RunOnFailure>
  24. class scope_exception {
  25. public:
  26. template <typename F>
  27. scope_exception(F f) : on_exit_(f), depth_(std::uncaught_exceptions()) {}
  28. scope_exception(scope_exception const &) = delete;
  29. scope_exception &operator=(scope_exception const &) = delete;
  30. scope_exception(scope_exception &&) = default;
  31. scope_exception &operator=(scope_exception &&) = default;
  32. ~scope_exception() noexcept(RunOnFailure) {
  33. if (on_exit_ && RunOnFailure == is_failure()) { on_exit_(); }
  34. }
  35. void release() { on_exit_ = {}; }
  36. private:
  37. bool is_failure() const {
  38. return std::uncaught_exceptions() > depth_;
  39. }
  40. private:
  41. std::function<void()> on_exit_;
  42. int depth_;
  43. };
  44. using scope_failure = scope_exception<true>;
  45. using scope_success = scope_exception<false>;
  46. #endif
  47. #if !defined(CONCAT)
  48. #define CONCAT2(A, B) A##B
  49. #define CONCAT(A, B) CONCAT2(A, B)
  50. #endif
  51. #define SCOPE_TYPE(t) CONCAT(scope_,t)
  52. #define SCOPE_GUARD_NAME(t) CONCAT(CONCAT(scope_guard_,t),__LINE__)
  53. #define scope(t) SCOPE_TYPE(t) SCOPE_GUARD_NAME(t) = [&]()
  54. #define scope_guard(t, f) SCOPE_TYPE(t) SCOPE_GUARD_NAME(t){f};