xref: /aosp_15_r20/external/pytorch/c10/util/ScopeExit.h (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
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   // NOLINTNEXTLINE(bugprone-forwarding-reference-overload)
scope_exit(Fp && F)19   explicit scope_exit(Fp&& F) : ExitFunction(std::forward<Fp>(F)) {}
20 
scope_exit(scope_exit && Rhs)21   scope_exit(scope_exit&& Rhs) noexcept
22       : ExitFunction(std::move(Rhs.ExitFunction)), Engaged(Rhs.Engaged) {
23     Rhs.release();
24   }
25   scope_exit(const scope_exit&) = delete;
26   scope_exit& operator=(scope_exit&&) = delete;
27   scope_exit& operator=(const scope_exit&) = delete;
28 
release()29   void release() {
30     Engaged = false;
31   }
32 
~scope_exit()33   ~scope_exit() {
34     if (Engaged) {
35       ExitFunction();
36     }
37   }
38 };
39 
40 // Keeps the callable object that is passed in, and execute it at the
41 // destruction of the returned object (usually at the scope exit where the
42 // returned object is kept).
43 //
44 // Interface is specified by p0052r2.
45 template <typename Callable>
make_scope_exit(Callable && F)46 scope_exit<std::decay_t<Callable>> make_scope_exit(Callable&& F) {
47   return scope_exit<std::decay_t<Callable>>(std::forward<Callable>(F));
48 }
49 
50 } // namespace c10
51