Home | History | Annotate | Download | only in gtl
      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_LIB_GTL_CLEANUP_H_
     43 #define TENSORFLOW_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:
     58   Cleanup() : released_(true), f_() {}
     59 
     60   template <typename G>
     61   explicit Cleanup(G&& f)          // NOLINT
     62       : f_(std::forward<G>(f)) {}  // NOLINT(build/c++11)
     63 
     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>
     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 
     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.
     90   F release() {
     91     released_ = true;
     92     return std::move(f_);
     93   }
     94 
     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>
    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_LIB_GTL_CLEANUP_H_
    114