scope.h 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. #pragma once
  2. #include <util/system/compiler.h>
  3. #include <util/system/defaults.h>
  4. #include <utility>
  5. namespace NPrivate {
  6. template <typename F>
  7. class TScopeGuard {
  8. public:
  9. TScopeGuard(const F& function)
  10. : Function_{function}
  11. {
  12. }
  13. TScopeGuard(F&& function)
  14. : Function_{std::move(function)}
  15. {
  16. }
  17. TScopeGuard(TScopeGuard&&) = default;
  18. TScopeGuard(const TScopeGuard&) = default;
  19. ~TScopeGuard() {
  20. Function_();
  21. }
  22. private:
  23. F Function_;
  24. };
  25. } // namespace NPrivate
  26. // \brief `Y_SCOPE_EXIT(captures) { body };`
  27. //
  28. // General implementaion of RAII idiom (resource acquisition is initialization). Executes
  29. // function upon return from the current scope.
  30. //
  31. // @note expects `body` to provide no-throw guarantee, otherwise whenever an exception
  32. // is thrown and leaves the outermost block of `body`, the function `std::terminate` is called.
  33. // @see http://drdobbs.com/184403758 for detailed motivation.
  34. #define Y_SCOPE_EXIT(...) const ::NPrivate::TScopeGuard Y_GENERATE_UNIQUE_ID(scopeGuard) Y_DECLARE_UNUSED = [__VA_ARGS__]() mutable -> void
  35. // \brief `Y_DEFER { body };`
  36. //
  37. // Same as `Y_SCOPE_EXIT` but doesn't require user to provide capture-list explicitly (it
  38. // implicitly uses `[&]` capture). Have same requirements for `body`.
  39. //
  40. // Inspired by `defer` statement in languages like Swift and Go.
  41. //
  42. // \code
  43. // auto item = s.pop();
  44. // bool ok = false;
  45. // Y_DEFER { if (!ok) { s.push(std::move(item)); } };
  46. // ... try handle `item` ...
  47. // ok = true;
  48. // \endcode
  49. #define Y_DEFER Y_SCOPE_EXIT(&)