Caffe2 - C++ API
A deep learning, cross platform ML framework
scope_guard.h
1 
6 #pragma once
7 
8 #include <cstddef>
9 #include <functional>
10 #include <new>
11 #include <type_traits>
12 #include <utility>
13 
14 namespace caffe2 {
15 
16 // Copied from folly/ScopeGuard.h
17 
60  public:
61  void dismiss() noexcept {
62  dismissed_ = true;
63  }
64 
65  protected:
66  ScopeGuardImplBase() noexcept : dismissed_(false) {}
67 
68  static ScopeGuardImplBase makeEmptyScopeGuard() noexcept {
69  return ScopeGuardImplBase{};
70  }
71 
72  template <typename T>
73  static const T& asConst(const T& t) noexcept {
74  return t;
75  }
76 
77  bool dismissed_;
78 };
79 
80 template <typename FunctionType>
82  public:
83  explicit ScopeGuardImpl(FunctionType& fn) noexcept(
84  std::is_nothrow_copy_constructible<FunctionType>::value)
86  asConst(fn),
87  makeFailsafe(std::is_nothrow_copy_constructible<FunctionType>{},
88  &fn)) {}
89 
90  explicit ScopeGuardImpl(const FunctionType& fn) noexcept(
91  std::is_nothrow_copy_constructible<FunctionType>::value)
93  fn,
94  makeFailsafe(std::is_nothrow_copy_constructible<FunctionType>{},
95  &fn)) {}
96 
97  explicit ScopeGuardImpl(FunctionType&& fn) noexcept(
98  std::is_nothrow_move_constructible<FunctionType>::value)
100  std::move_if_noexcept(fn),
101  makeFailsafe(std::is_nothrow_move_constructible<FunctionType>{},
102  &fn)) {}
103 
104  ScopeGuardImpl(ScopeGuardImpl&& other) noexcept(
105  std::is_nothrow_move_constructible<FunctionType>::value)
106  : function_(std::move_if_noexcept(other.function_)) {
107  // If the above line attempts a copy and the copy throws, other is
108  // left owning the cleanup action and will execute it (or not) depending
109  // on the value of other.dismissed_. The following lines only execute
110  // if the move/copy succeeded, in which case *this assumes ownership of
111  // the cleanup action and dismisses other.
112  dismissed_ = other.dismissed_;
113  other.dismissed_ = true;
114  }
115 
116  ~ScopeGuardImpl() noexcept {
117  if (!dismissed_) {
118  execute();
119  }
120  }
121 
122  private:
123  static ScopeGuardImplBase makeFailsafe(std::true_type, const void*) noexcept {
124  return makeEmptyScopeGuard();
125  }
126 
127  template <typename Fn>
128  static auto makeFailsafe(std::false_type, Fn* fn) noexcept
130  return ScopeGuardImpl<decltype(std::ref(*fn))>{std::ref(*fn)};
131  }
132 
133  template <typename Fn>
134  explicit ScopeGuardImpl(Fn&& fn, ScopeGuardImplBase&& failsafe)
135  : ScopeGuardImplBase{}, function_(std::forward<Fn>(fn)) {
136  failsafe.dismiss();
137  }
138 
139  void* operator new(std::size_t) = delete;
140 
141  void execute() noexcept { function_(); }
142 
143  FunctionType function_;
144 };
145 
146 template <typename FunctionType>
148 MakeGuard(FunctionType&& fn) noexcept(
149  std::is_nothrow_constructible<typename std::decay<FunctionType>::type,
150  FunctionType>::value) {
152  std::forward<FunctionType>(fn));
153 }
154 
159 
160 } // namespaces
Simple registry implementation in Caffe2 that uses static variables to register object creators durin...
ScopeGuardImplBase && ScopeGuard
This is largely unneeded if you just use auto for your guards.
Definition: scope_guard.h:158
ScopeGuard is a general implementation of the "Initialization is Resource Acquisition" idiom...
Definition: scope_guard.h:59