userver: userver/utils/scope_guard.hpp Source File
Loading...
Searching...
No Matches
scope_guard.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/scope_guard.hpp
4/// @brief @copybrief utils::ScopeGuard
5
6#include <exception>
7#include <functional>
8
9#include <userver/logging/log.hpp>
10#include <userver/utils/assert.hpp>
11
12USERVER_NAMESPACE_BEGIN
13
14namespace utils {
15
16/// @ingroup userver_universal userver_containers
17///
18/// @brief a helper class to perform actions on scope exit
19///
20/// Usage example:
21/// @snippet universal/src/utils/scope_guard_test.cpp ScopeGuard usage example
22///
23/// @note exception handling is done in such way that std::terminate will not be
24/// called: in the normal path of execution, exception from handler will
25/// propagate into client code, but if we leave scope because of an exception,
26/// handler's exception, if thrown, will be silenced and written into log to
27/// avoid std::terminate
28class ScopeGuard final {
29public:
30 using Callback = std::function<void()>;
31
32 explicit ScopeGuard(Callback callback)
33 : callback_(std::move(callback)),
34 exceptions_on_enter_(std::uncaught_exceptions())
35 {}
36
37 ScopeGuard(const ScopeGuard&) = delete;
38 ScopeGuard(ScopeGuard&&) = delete;
39
40 ScopeGuard& operator=(const ScopeGuard&) = delete;
41 ScopeGuard& operator=(ScopeGuard&&) = delete;
42
43 ~ScopeGuard() noexcept(false) {
44 if (!callback_) {
45 return;
46 }
47
48 if (std::uncaught_exceptions() != exceptions_on_enter_) {
49 // keep all exceptions inside the destructor to avoid std::terminate
50 try {
51 callback_();
52 } catch (const std::exception& e) {
53 UASSERT_MSG(false, "exception is thrown during stack unwinding");
54 LOG_ERROR() << "Exception is thrown during stack unwinding - ignoring: " << e;
55 }
56 } else {
57 // safe to throw
58 callback_();
59 }
60 }
61
62 void Release() noexcept { callback_ = {}; }
63
64private:
65 Callback callback_;
66 const int exceptions_on_enter_;
67};
68
69} // namespace utils
70
71USERVER_NAMESPACE_END