/src/rocksdb/util/defer.h
Line | Count | Source |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under both the GPLv2 (found in the |
3 | | // COPYING file in the root directory) and Apache 2.0 License |
4 | | // (found in the LICENSE.Apache file in the root directory). |
5 | | |
6 | | #pragma once |
7 | | |
8 | | #include <functional> |
9 | | |
10 | | #include "rocksdb/rocksdb_namespace.h" |
11 | | |
12 | | namespace ROCKSDB_NAMESPACE { |
13 | | |
14 | | // Defers the execution of the provided function until the Defer |
15 | | // object goes out of scope. |
16 | | // |
17 | | // Usage example: |
18 | | // |
19 | | // Status DeferTest() { |
20 | | // Status s; |
21 | | // Defer defer([&s]() { |
22 | | // if (!s.ok()) { |
23 | | // // do cleanups ... |
24 | | // } |
25 | | // }); |
26 | | // // do something ... |
27 | | // if (!s.ok()) return; |
28 | | // // do some other things ... |
29 | | // return s; |
30 | | // } |
31 | | // |
32 | | // The above code ensures that cleanups will always happen on returning. |
33 | | // |
34 | | // Without the help of Defer, you can |
35 | | // 1. every time when !s.ok(), do the cleanup; |
36 | | // 2. instead of returning when !s.ok(), continue the work only when s.ok(), |
37 | | // but sometimes, this might lead to nested blocks of "if (s.ok()) {...}". |
38 | | // |
39 | | // With the help of Defer, you can centralize the cleanup logic inside the |
40 | | // lambda passed to Defer, and you can return immediately on failure when |
41 | | // necessary. |
42 | | class Defer final { |
43 | | public: |
44 | 38.6k | explicit Defer(std::function<void()>&& fn) : fn_(std::move(fn)) {} |
45 | 38.6k | ~Defer() { fn_(); } |
46 | | |
47 | | // Disallow copy. |
48 | | Defer(const Defer&) = delete; |
49 | | Defer& operator=(const Defer&) = delete; |
50 | | |
51 | | private: |
52 | | std::function<void()> fn_; |
53 | | }; |
54 | | |
55 | | // An RAII utility object that saves the current value of an object so that |
56 | | // it can be overwritten, and restores it to the saved value when the |
57 | | // SaveAndRestore object goes out of scope. |
58 | | template <typename T> |
59 | | class SaveAndRestore { |
60 | | public: |
61 | | // obj is non-null pointer to value to be saved and later restored. |
62 | 9.03k | explicit SaveAndRestore(T* obj) : obj_(obj), saved_(*obj) {} |
63 | | // new_value is stored in *obj |
64 | | SaveAndRestore(T* obj, const T& new_value) |
65 | | : obj_(obj), saved_(std::move(*obj)) { |
66 | | *obj = new_value; |
67 | | } |
68 | | SaveAndRestore(T* obj, T&& new_value) : obj_(obj), saved_(std::move(*obj)) { |
69 | | *obj = std::move(new_value); |
70 | | } |
71 | 9.03k | ~SaveAndRestore() { *obj_ = std::move(saved_); } |
72 | | |
73 | | // No copies |
74 | | SaveAndRestore(const SaveAndRestore&) = delete; |
75 | | SaveAndRestore& operator=(const SaveAndRestore&) = delete; |
76 | | |
77 | | private: |
78 | | T* const obj_; |
79 | | T saved_; |
80 | | }; |
81 | | |
82 | | } // namespace ROCKSDB_NAMESPACE |