Caffe2 - C++ API
A deep learning, cross platform ML framework
scope_guard.h
1 
22 #pragma once
23 
24 #include <cstddef>
25 #include <functional>
26 #include <new>
27 #include <type_traits>
28 #include <utility>
29 
30 namespace caffe2 {
31 
32 // Copied from folly/ScopeGuard.h
33 
34 namespace detail {
35 
37  public:
38  void dismiss() noexcept {
39  dismissed_ = true;
40  }
41 
42  protected:
43  ScopeGuardImplBase() noexcept : dismissed_(false) {}
44 
45  static ScopeGuardImplBase makeEmptyScopeGuard() noexcept {
46  return ScopeGuardImplBase{};
47  }
48 
49  template <typename T>
50  static const T& asConst(const T& t) noexcept {
51  return t;
52  }
53 
54  bool dismissed_;
55 };
56 
57 template <typename FunctionType>
59  public:
60  explicit ScopeGuardImpl(FunctionType& fn) noexcept(
61  std::is_nothrow_copy_constructible<FunctionType>::value)
63  asConst(fn),
64  makeFailsafe(std::is_nothrow_copy_constructible<FunctionType>{},
65  &fn)) {}
66 
67  explicit ScopeGuardImpl(const FunctionType& fn) noexcept(
68  std::is_nothrow_copy_constructible<FunctionType>::value)
70  fn,
71  makeFailsafe(std::is_nothrow_copy_constructible<FunctionType>{},
72  &fn)) {}
73 
74  explicit ScopeGuardImpl(FunctionType&& fn) noexcept(
75  std::is_nothrow_move_constructible<FunctionType>::value)
77  std::move_if_noexcept(fn),
78  makeFailsafe(std::is_nothrow_move_constructible<FunctionType>{},
79  &fn)) {}
80 
81  ScopeGuardImpl(ScopeGuardImpl&& other) noexcept(
82  std::is_nothrow_move_constructible<FunctionType>::value)
83  : function_(std::move_if_noexcept(other.function_)) {
84  // If the above line attempts a copy and the copy throws, other is
85  // left owning the cleanup action and will execute it (or not) depending
86  // on the value of other.dismissed_. The following lines only execute
87  // if the move/copy succeeded, in which case *this assumes ownership of
88  // the cleanup action and dismisses other.
89  dismissed_ = other.dismissed_;
90  other.dismissed_ = true;
91  }
92 
93  ~ScopeGuardImpl() noexcept {
94  if (!dismissed_) {
95  execute();
96  }
97  }
98 
99  private:
100  static ScopeGuardImplBase makeFailsafe(std::true_type, const void*) noexcept {
101  return makeEmptyScopeGuard();
102  }
103 
104  template <typename Fn>
105  static auto makeFailsafe(std::false_type, Fn* fn) noexcept
107  return ScopeGuardImpl<decltype(std::ref(*fn))>{std::ref(*fn)};
108  }
109 
110  template <typename Fn>
111  explicit ScopeGuardImpl(Fn&& fn, ScopeGuardImplBase&& failsafe)
112  : ScopeGuardImplBase{}, function_(std::forward<Fn>(fn)) {
113  failsafe.dismiss();
114  }
115 
116  void* operator new(std::size_t) = delete;
117 
118  void execute() noexcept { function_(); }
119 
120  FunctionType function_;
121 };
122 
123 template <typename F>
125 
126 } // namespace detail
127 
168 template <typename F>
170  noexcept(detail::ScopeGuardImplDecay<F>(static_cast<F&&>(f)))) {
171  return detail::ScopeGuardImplDecay<F>(static_cast<F&&>(f));
172 }
173 
174 } // namespaces
detail::ScopeGuardImplDecay< F > MakeGuard(F &&f) noexcept(noexcept(detail::ScopeGuardImplDecay< F >(static_cast< F && >(f))))
ScopeGuard is a general implementation of the "Initialization is Resource Acquisition" idiom...
Definition: scope_guard.h:169
Copyright (c) 2016-present, Facebook, Inc.