forked from RobotLocomotion/drake
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscope_exit.h
61 lines (52 loc) · 1.45 KB
/
scope_exit.h
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
#pragma once
#include <functional>
#include <utility>
#include "drake/common/drake_copyable.h"
#include "drake/common/drake_throw.h"
namespace drake {
/// Helper class to create a scope exit guard -- an object that when destroyed
/// runs `func`. This is useful to apply RAII to third-party code that only
/// supports manual acquire and release operations.
///
/// Example:
///
/// @code
/// void some_function() {
/// void* foo = ::malloc(10);
/// ScopeExit guard([foo]() {
/// ::free(foo);
/// });
///
/// // ...
/// if (condition) { throw std::runtime_error("..."); }
/// // ...
/// }
/// @endcode
///
/// Here, the allocation of `foo` will always be free'd no matter whether
/// `some_function` returns normally or via an exception.
class ScopeExit final {
public:
DRAKE_NO_COPY_NO_MOVE_NO_ASSIGN(ScopeExit);
/// Creates a resource that will call `func` when destroyed. Note that
/// `func()` should not throw an exception, since it will typically be
/// invoked during stack unwinding.
explicit ScopeExit(std::function<void()> func)
: func_(std::move(func)) {
DRAKE_THROW_UNLESS(func_ != nullptr);
}
/// Invokes the `func` that was passed into the constructor, unless this has
/// been disarmed.
~ScopeExit() {
if (func_) {
func_();
}
}
/// Disarms this guard, so that the destructor has no effect.
void Disarm() {
func_ = nullptr;
}
private:
std::function<void()> func_;
};
} // namespace drake