1 | #pragma once |
2 | |
3 | #include <type_traits> |
4 | #include <utility> |
5 | |
6 | namespace c10 { |
7 | |
8 | /** |
9 | * Mostly copied from https://llvm.org/doxygen/ScopeExit_8h_source.html |
10 | */ |
11 | template <typename Callable> |
12 | class scope_exit { |
13 | Callable ExitFunction; |
14 | bool Engaged = true; // False once moved-from or release()d. |
15 | |
16 | public: |
17 | template <typename Fp> |
18 | // constructor accepting a forwarding reference can hide the |
19 | // move constructor |
20 | // @lint-ignore CLANGTIDY |
21 | explicit scope_exit(Fp&& F) : ExitFunction(std::forward<Fp>(F)) {} |
22 | |
23 | scope_exit(scope_exit&& Rhs) noexcept |
24 | : ExitFunction(std::move(Rhs.ExitFunction)), Engaged(Rhs.Engaged) { |
25 | Rhs.release(); |
26 | } |
27 | scope_exit(const scope_exit&) = delete; |
28 | scope_exit& operator=(scope_exit&&) = delete; |
29 | scope_exit& operator=(const scope_exit&) = delete; |
30 | |
31 | void release() { |
32 | Engaged = false; |
33 | } |
34 | |
35 | ~scope_exit() { |
36 | if (Engaged) { |
37 | ExitFunction(); |
38 | } |
39 | } |
40 | }; |
41 | |
42 | // Keeps the callable object that is passed in, and execute it at the |
43 | // destruction of the returned object (usually at the scope exit where the |
44 | // returned object is kept). |
45 | // |
46 | // Interface is specified by p0052r2. |
47 | template <typename Callable> |
48 | scope_exit<typename std::decay<Callable>::type> make_scope_exit(Callable&& F) { |
49 | return scope_exit<typename std::decay<Callable>::type>( |
50 | std::forward<Callable>(F)); |
51 | } |
52 | |
53 | } // namespace c10 |
54 | |