userver: userver/utils/fast_scope_guard.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
fast_scope_guard.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <type_traits>
4#include <utility>
5
6/// @file userver/utils/fast_scope_guard.hpp
7/// @brief @copybrief utils::FastScopeGuard
8
9USERVER_NAMESPACE_BEGIN
10
11namespace utils {
12
13/// @ingroup userver_universal userver_containers
14///
15/// @brief a helper class to perform actions on scope exit
16///
17/// The lambda argument must be explicitly marked as `noexcept`. Only use
18/// FastScopeGuard if it's proven that the lambda body is `noexcept`, otherwise
19/// use ScopeGuard.
20///
21/// Usage example:
22/// @snippet universal/src/utils/fast_scope_guard_test.cpp FastScopeGuard
23///
24/// @see ScopeGuard for type-erasure and throwing functor support
25template <typename Callback>
26class FastScopeGuard final {
27 public:
28 static_assert(std::is_nothrow_move_constructible_v<Callback>);
29
30 static_assert(
31 std::is_nothrow_invocable_r_v<void, Callback&&>,
32 "If the functions called in the body of the lambda are all 'noexcept', "
33 "please mark the lambda itself as 'noexcept'. If however, the contents "
34 "are not 'noexcept', use 'ScopeGuard' instead of 'FastScopeGuard'.");
35
36 constexpr explicit FastScopeGuard(Callback callback) noexcept
37 : callback_(std::move(callback)) {}
38
39 constexpr FastScopeGuard(FastScopeGuard&& other) noexcept
40 : callback_(std::move(other.callback_)),
41 is_active_(std::exchange(other.is_active_, false)) {}
42
43 constexpr FastScopeGuard& operator=(FastScopeGuard&& other) noexcept {
44 if (this != &other) {
45 callback_ = std::move(other.callback_);
46 is_active_ = std::exchange(other.is_active_, false);
47 }
48 return *this;
49 }
50
51 ~FastScopeGuard() {
52 if (is_active_) std::move(callback_)();
53 }
54
55 constexpr void Release() noexcept { is_active_ = false; }
56
57 private:
58 Callback callback_;
59
60 // should be optimized out if 'Release' is not called
61 bool is_active_{true};
62};
63
64} // namespace utils
65
66USERVER_NAMESPACE_END