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