Dev Essential  1.6.3
Loading...
Searching...
No Matches
scopeguard.h
Go to the documentation of this file.
1
17
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
35namespace a_util {
36
41
55template <class F>
56class ScopeGuard {
57public:
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
106private:
107 bool _enabled = true;
108 typename std::decay<F>::type _f;
109};
110
127template <class F>
128inline auto scopeExit(F&& f)
129{
130 return ScopeGuard<F>(std::forward<F>(f));
131}
132
133#ifdef A_UTIL_HAVE_UNCAUGHT_EXCEPTIONS
134
136namespace detail {
137
138template <class F, bool ExecuteOnFailure>
139class ScopeGuard final : public ::a_util::ScopeGuard<F> {
140public:
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
154private:
155 const int _uncaught_exceptions_on_entry = std::uncaught_exceptions();
156};
157
158} // namespace detail
160
168template <class F>
169inline auto scopeSuccess(F&& f)
170{
171 return detail::ScopeGuard<F, /*ExecuteOnFailure=*/false>(std::forward<F>(f));
172}
173
179template <class F>
180inline 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
188
189} // namespace a_util
190
191#endif // A_UTIL_SCOPEGUARD_HEADER_INCLUDED
Definition scopeguard.h:56
ScopeGuard(F &&f)
Definition scopeguard.h:76
void rehire() noexcept
Definition scopeguard.h:101
~ScopeGuard()
Definition scopeguard.h:83
void dismiss() noexcept
Definition scopeguard.h:93
auto scopeExit(F &&f)
Definition scopeguard.h:128
Serves as the root component, with common functionality documented in core functionality.
Definition base.h:24