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)46scope_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