1#pragma once
2
3#include <type_traits>
4#include <utility>
5
6namespace c10 {
7
8/**
9 * Mostly copied from https://llvm.org/doxygen/ScopeExit_8h_source.html
10 */
11template <typename Callable>
12class 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.
47template <typename Callable>
48scope_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