kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/cxx/common/scope_guard.h (about)

     1  /*
     2   * Copyright 2017 The Kythe Authors. All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *   http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  #ifndef KYTHE_CXX_COMMON_SCOPE_GUARD_H
    18  #define KYTHE_CXX_COMMON_SCOPE_GUARD_H
    19  
    20  #include <utility>
    21  
    22  #include "absl/base/attributes.h"
    23  #include "absl/log/check.h"
    24  
    25  namespace kythe {
    26  
    27  /// \brief A move-only RAII object that calls a stored cleanup functor when
    28  /// destroyed.
    29  template <typename F>
    30  class ABSL_MUST_USE_RESULT ScopeGuard {
    31   public:
    32    explicit ScopeGuard(F&& Fn) : Fn(std::forward<F>(Fn)) {}
    33    ScopeGuard(ScopeGuard&& O) : Released(O.Released), Fn(std::move(O.Fn)) {
    34      O.Released = true;
    35    }
    36    ~ScopeGuard() {
    37      if (!Released) Fn();
    38    }
    39  
    40   private:
    41    bool Released = false;
    42    F Fn;
    43  };
    44  
    45  /// \brief Returns a type-deduced ScopeGuard for the provided function object.
    46  template <typename F>
    47  ScopeGuard<F> MakeScopeGuard(F&& Fn) {
    48    return ScopeGuard<F>(std::forward<F>(Fn));
    49  }
    50  
    51  /// \brief Restores the type of a stacklike container of `ElementType`.
    52  template <typename StackType>
    53  struct StackSizeRestorer {
    54    void operator()() const {
    55      CHECK_LE(Size, Target->size());
    56      while (Size < Target->size()) {
    57        Target->pop_back();
    58      }
    59    }
    60  
    61    StackType* Target;
    62    decltype(Target->size()) Size;
    63  };
    64  
    65  /// \brief Handles the restoration of a stacklike container.
    66  ///
    67  /// \example
    68  /// \code
    69  ///   auto R = RestoreStack(SomeStack);
    70  /// \endcode
    71  template <typename StackType>
    72  ScopeGuard<StackSizeRestorer<StackType>> RestoreStack(StackType& S) {
    73    return ScopeGuard<StackSizeRestorer<StackType>>({&S, S.size()});
    74  }
    75  
    76  /// \brief Pops the final element off the Target stack at destruction.
    77  template <typename StackType>
    78  struct BackPopper {
    79    void operator()() const { Target->pop_back(); }
    80  
    81    StackType* Target;
    82  };
    83  
    84  /// \brief Pushes the value onto the stack and returns a sentinel which will
    85  /// remove it at destruction.
    86  template <typename StackType,
    87            typename ValueType = typename StackType::value_type>
    88  ScopeGuard<BackPopper<StackType>> PushScope(StackType& Target,
    89                                              ValueType&& Value) {
    90    Target.push_back(std::forward<ValueType>(Value));
    91    return ScopeGuard<BackPopper<StackType>>({&Target});
    92  }
    93  
    94  /// \brief Restores the recorded value.
    95  template <typename ValueType>
    96  struct ValueRestorer {
    97    void operator()() const { *Target = Value; }
    98  
    99    ValueType* Target;
   100    ValueType Value;
   101  };
   102  
   103  /// \brief Records the current value of the target and returns a sentinel
   104  /// which will restore it upon destruction.
   105  template <typename ValueType>
   106  ScopeGuard<ValueRestorer<ValueType>> RestoreValue(ValueType& Value) {
   107    return ScopeGuard<ValueRestorer<ValueType>>({&Value, Value});
   108  }
   109  
   110  }  // namespace kythe
   111  
   112  #endif  // KYTHE_CXX_COMMON_SCOPE_GUARD_H