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_v<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 static_assert(std::is_void_v<std::invoke_result_t<Callback&&>>,
37 "Return type of Callback function should be void");
38
39 static_assert(std::is_nothrow_destructible_v<Callback>,
40 "Callback function destructor should be noexcept");
41
42 constexpr explicit FastScopeGuard(Callback callback) noexcept
43 : callback_(std::move(callback)) {}
44
45 constexpr FastScopeGuard(FastScopeGuard&& other) noexcept
46 : callback_(std::move(other.callback_)),
47 is_active_(std::exchange(other.is_active_, false)) {}
48
49 constexpr FastScopeGuard& operator=(FastScopeGuard&& other) noexcept {
50 if (this != &other) {
51 callback_ = std::move(other.callback_);
52 is_active_ = std::exchange(other.is_active_, false);
53 }
54 return *this;
55 }
56
57 ~FastScopeGuard() {
58 if (is_active_) std::move(callback_)();
59 }
60
61 constexpr void Release() noexcept { is_active_ = false; }
62
63 private:
64 Callback callback_;
65
66 // should be optimized out if 'Release' is not called
67 bool is_active_{true};
68};
69
70} // namespace utils
71
72USERVER_NAMESPACE_END