userver: userver/utils/fast_scope_guard.hpp Source File
Loading...
Searching...
No Matches
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