• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2016 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 // MakeCleanup(f) returns an RAII cleanup object that calls 'f' in its
17 // destructor. The easiest way to use MakeCleanup is with a lambda argument,
18 // capturing the return value in an 'auto' local variable. Most users will not
19 // need more sophisticated syntax than that.
20 //
21 // Example:
22 //   void func() {}
23 //     FILE* fp = fopen("data.txt", "r");
24 //     if (fp == nullptr) return;
25 //     auto fp_cleaner = gtl::MakeCleanup([fp] { fclose(fp); });
26 //     // No matter what, fclose(fp) will happen.
27 //     DataObject d;
28 //     while (ReadDataObject(fp, &d)) {
29 //       if (d.IsBad()) {
30 //         LOG(ERROR) << "Bad Data";
31 //         return;
32 //       }
33 //       PushGoodData(d);
34 //     }
35 //   }
36 //
37 // You can use Cleanup<F> directly, instead of using MakeCleanup and auto,
38 // but there's rarely a reason to do that.
39 //
40 // You can call 'release()' on a Cleanup object to cancel the cleanup.
41 
42 #ifndef TENSORFLOW_CORE_LIB_GTL_CLEANUP_H_
43 #define TENSORFLOW_CORE_LIB_GTL_CLEANUP_H_
44 
45 #include <type_traits>
46 #include <utility>
47 
48 #include "tensorflow/core/platform/macros.h"
49 
50 namespace tensorflow {
51 namespace gtl {
52 
53 // A move-only RAII object that calls a stored cleanup functor when
54 // destroyed. Cleanup<F> is the return type of gtl::MakeCleanup(F).
55 template <typename F>
56 class Cleanup {
57  public:
Cleanup()58   Cleanup() : released_(true), f_() {}
59 
60   template <typename G>
Cleanup(G && f)61   explicit Cleanup(G&& f)          // NOLINT
62       : f_(std::forward<G>(f)) {}  // NOLINT(build/c++11)
63 
Cleanup(Cleanup && src)64   Cleanup(Cleanup&& src)  // NOLINT
65       : released_(src.is_released()), f_(src.release()) {}
66 
67   // Implicitly move-constructible from any compatible Cleanup<G>.
68   // The source will be released as if src.release() were called.
69   // A moved-from Cleanup can be safely destroyed or reassigned.
70   template <typename G>
Cleanup(Cleanup<G> && src)71   Cleanup(Cleanup<G>&& src)  // NOLINT
72       : released_(src.is_released()), f_(src.release()) {}
73 
74   // Assignment to a Cleanup object behaves like destroying it
75   // and making a new one in its place, analogous to unique_ptr
76   // semantics.
77   Cleanup& operator=(Cleanup&& src) {  // NOLINT
78     if (!released_) f_();
79     released_ = src.released_;
80     f_ = src.release();
81     return *this;
82   }
83 
~Cleanup()84   ~Cleanup() {
85     if (!released_) f_();
86   }
87 
88   // Releases the cleanup function instead of running it.
89   // Hint: use c.release()() to run early.
release()90   F release() {
91     released_ = true;
92     return std::move(f_);
93   }
94 
is_released()95   bool is_released() const { return released_; }
96 
97  private:
98   static_assert(!std::is_reference<F>::value, "F must not be a reference");
99 
100   bool released_ = false;
101   F f_;
102 };
103 
104 template <int&... ExplicitParameterBarrier, typename F,
105           typename DecayF = typename std::decay<F>::type>
MakeCleanup(F && f)106 TF_MUST_USE_RESULT Cleanup<DecayF> MakeCleanup(F&& f) {
107   return Cleanup<DecayF>(std::forward<F>(f));
108 }
109 
110 }  // namespace gtl
111 }  // namespace tensorflow
112 
113 #endif  // TENSORFLOW_CORE_LIB_GTL_CLEANUP_H_
114