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