blob: 0761e2962f204f1cac60b792855471d2b4d16061 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
#pragma once
#include <util/system/compiler.h>
#include <util/system/defaults.h>
#include <utility>
namespace NPrivate {
template <typename F>
class TScopeGuard {
public:
TScopeGuard(const F& function)
: Function_{function}
{
}
TScopeGuard(F&& function)
: Function_{std::move(function)}
{
}
TScopeGuard(TScopeGuard&&) = default;
TScopeGuard(const TScopeGuard&) = default;
~TScopeGuard() {
Function_();
}
private:
F Function_;
};
struct TMakeGuardHelper {
template <class F>
TScopeGuard<F> operator|(F&& function) const {
return std::forward<F>(function);
}
};
} // namespace NPrivate
// \brief `Y_SCOPE_EXIT(captures) { body };`
//
// General implementaion of RAII idiom (resource acquisition is initialization). Executes
// function upon return from the current scope.
//
// @note expects `body` to provide no-throw guarantee, otherwise whenever an exception
// is thrown and leaves the outermost block of `body`, the function `std::terminate` is called.
// @see http://drdobbs.com/184403758 for detailed motivation.
#define Y_SCOPE_EXIT(...) const auto Y_GENERATE_UNIQUE_ID(scopeGuard) Y_DECLARE_UNUSED = ::NPrivate::TMakeGuardHelper{} | [__VA_ARGS__]() mutable -> void
// \brief `Y_DEFER { body };`
//
// Same as `Y_SCOPE_EXIT` but doesn't require user to provide capture-list explicitly (it
// implicitly uses `[&]` capture). Have same requirements for `body`.
//
// Inspired by `defer` statement in languages like Swift and Go.
//
// \code
// auto item = s.pop();
// bool ok = false;
// Y_DEFER { if (!ok) { s.push(std::move(item)); } };
// ... try handle `item` ...
// ok = true;
// \endcode
#define Y_DEFER Y_SCOPE_EXIT(&)
|