blob: b4a1749a72f1ac70f0f6654a84566b9f6ade5365 (
plain)
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
|
#pragma once
#include "Macros.hpp"
#include <utility>
template <class TCleanupFunc>
class ScopeGuard {
private:
TCleanupFunc mFunc;
bool mDismissed = false;
public:
/// Specifically left this implicit so that constructs like
/// \code
/// ScopeGuard sg = [&]() { res.Cleanup(); };
/// \endcode
/// would work. It is highly discourage and unlikely that one would want to use ScopeGuard as a function
/// parameter, so the normal argument that implicit conversion are harmful doesn't really apply here.
// Deliberately not explicit to allow usages like: ScopeGuard var = lambda;
ScopeGuard(TCleanupFunc&& function) noexcept
: mFunc{ std::move(function) } {
}
~ScopeGuard() noexcept {
if (!mDismissed) {
mFunc();
}
}
ScopeGuard(const ScopeGuard&) = delete;
ScopeGuard& operator=(const ScopeGuard&) = delete;
ScopeGuard(ScopeGuard&& that) noexcept
: mFunc{ std::move(that.mFunc) } {
that.Cancel();
}
ScopeGuard& operator=(ScopeGuard&& that) noexcept {
if (!mDismissed) {
mFunc();
}
this->mFunc = std::move(that.mFunc);
this->cancelled = std::exchange(that.cancelled, true);
}
void Dismiss() noexcept {
mDismissed = true;
}
};
#define SCOPE_GUARD(name) ScopeGuard name = [&]()
#define DEFER ScopeGuard UNIQUE_NAME(scopeGuard) = [&]()
|