ADTF  3.18.2
scopeguard.h
Go to the documentation of this file.
1 
18 #ifndef A_UTIL_SCOPEGUARD_HEADER_INCLUDED
19 #define A_UTIL_SCOPEGUARD_HEADER_INCLUDED
20 
21 #include <exception>
22 #include <type_traits>
23 #include <utility>
24 
25 #if ((defined _MSC_VER) && (_MSVC_LANG >= 201703L)) || \
26  ((!defined _MSC_VER) && (__cplusplus >= 201703L))
27 // C++17 is required for std::uncaught_exceptions. Code using it is enabled conditionally.
28 // MSVC does not correctly set the value of __cplusplus. Therefore there is an extra test for
29 // MSVC in the preprocessor directive.
30 // See https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/
31 #define A_UTIL_HAVE_UNCAUGHT_EXCEPTIONS
32 #define A_UTIL_HAVE_GUARANTEED_COPY_ELISION
33 #endif
34 
35 namespace a_util {
36 
55 template <class F>
56 class ScopeGuard {
57 public:
58  ScopeGuard() = delete;
59  ScopeGuard(const ScopeGuard&) = delete;
60  ScopeGuard& operator=(const ScopeGuard&) = delete;
61  ScopeGuard& operator=(ScopeGuard&& other) = delete;
62 
63 #ifdef A_UTIL_HAVE_GUARANTEED_COPY_ELISION
64  ScopeGuard(ScopeGuard&&) = delete;
65 #else
66  ScopeGuard(ScopeGuard&& other) : _enabled(other._enabled), _f(other._f)
67  {
68  other.dismiss();
69  }
70 #endif // A_UTIL_HAVE_GUARANTEED_COPY_ELISION
71 
76  explicit ScopeGuard(F&& f) : _f(std::forward<F>(f))
77  {
78  }
79 
84  {
85  if (_enabled) {
86  _f();
87  }
88  }
89 
93  void dismiss() noexcept
94  {
95  _enabled = false;
96  }
97 
101  void rehire() noexcept
102  {
103  _enabled = true;
104  }
105 
106 private:
107  bool _enabled = true;
108  typename std::decay<F>::type _f;
109 };
110 
127 template <class F>
128 inline auto scopeExit(F&& f)
129 {
130  return ScopeGuard<F>(std::forward<F>(f));
131 }
132 
133 #ifdef A_UTIL_HAVE_UNCAUGHT_EXCEPTIONS
134 
136 namespace detail {
137 
138 template <class F, bool ExecuteOnFailure>
139 class ScopeGuard final : public ::a_util::ScopeGuard<F> {
140 public:
141  explicit ScopeGuard(F&& f) : ::a_util::ScopeGuard<F>(std::forward<F>(f))
142  {
143  }
144 
145  ~ScopeGuard()
146  {
147  const auto uncaught_exceptions_on_exit = std::uncaught_exceptions();
148  const auto success = _uncaught_exceptions_on_entry == uncaught_exceptions_on_exit;
149  if (ExecuteOnFailure == success) {
150  this->dismiss();
151  }
152  }
153 
154 private:
155  const int _uncaught_exceptions_on_entry = std::uncaught_exceptions();
156 };
157 
158 } // namespace detail
168 template <class F>
169 inline auto scopeSuccess(F&& f)
170 {
171  return detail::ScopeGuard<F, /*ExecuteOnFailure=*/false>(std::forward<F>(f));
172 }
173 
179 template <class F>
180 inline auto scopeFailure(F&& f)
181 {
182  return detail::ScopeGuard<F, /*ExecuteOnFailure=*/true>(std::forward<F>(f));
183 }
184 
185 #endif // A_UTIL_HAVE_UNCAUGHT_EXCEPTIONS
186 
189 } // namespace a_util
190 
191 #endif // A_UTIL_SCOPEGUARD_HEADER_INCLUDED
Scope guard executing a callable object of type F on scope exit.
Definition: scopeguard.h:56
ScopeGuard(F &&f)
Ctor.
Definition: scopeguard.h:76
~ScopeGuard()
Destroy the scope guard object and execute the callable if execution is enabled.
Definition: scopeguard.h:83
void dismiss() noexcept
Dismiss the execution of the callable on scope exit.
Definition: scopeguard.h:93
void rehire() noexcept
Rehire the execution of the callable on scope exit.
Definition: scopeguard.h:101
auto scopeExit(F &&f)
Creates a scope guard executing callable f on scope exit.
Definition: scopeguard.h:128
Serves as the root component, with common functionality documented in core functionality.
Definition: base.h:24