1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_AUTO_RESET_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_AUTO_RESET_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <utility> 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h" 11*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr_exclusion.h" 12*6777b538SAndroid Build Coastguard Worker 13*6777b538SAndroid Build Coastguard Worker // base::AutoReset<> is useful for setting a variable to a new value only within 14*6777b538SAndroid Build Coastguard Worker // a particular scope. An base::AutoReset<> object resets a variable to its 15*6777b538SAndroid Build Coastguard Worker // original value upon destruction, making it an alternative to writing 16*6777b538SAndroid Build Coastguard Worker // "var = false;" or "var = old_val;" at all of a block's exit points. 17*6777b538SAndroid Build Coastguard Worker // 18*6777b538SAndroid Build Coastguard Worker // This should be obvious, but note that an base::AutoReset<> instance should 19*6777b538SAndroid Build Coastguard Worker // have a shorter lifetime than its scoped_variable, to prevent invalid memory 20*6777b538SAndroid Build Coastguard Worker // writes when the base::AutoReset<> object is destroyed. 21*6777b538SAndroid Build Coastguard Worker 22*6777b538SAndroid Build Coastguard Worker namespace base { 23*6777b538SAndroid Build Coastguard Worker 24*6777b538SAndroid Build Coastguard Worker template <typename T> 25*6777b538SAndroid Build Coastguard Worker class [[maybe_unused, nodiscard]] AutoReset { 26*6777b538SAndroid Build Coastguard Worker public: 27*6777b538SAndroid Build Coastguard Worker template <typename U> AutoReset(T * scoped_variable,U && new_value)28*6777b538SAndroid Build Coastguard Worker AutoReset(T* scoped_variable, U&& new_value) 29*6777b538SAndroid Build Coastguard Worker : scoped_variable_(scoped_variable), 30*6777b538SAndroid Build Coastguard Worker original_value_( 31*6777b538SAndroid Build Coastguard Worker std::exchange(*scoped_variable_, std::forward<U>(new_value))) {} 32*6777b538SAndroid Build Coastguard Worker 33*6777b538SAndroid Build Coastguard Worker // A constructor that's useful for asserting the old value of 34*6777b538SAndroid Build Coastguard Worker // `scoped_variable`, especially when it's inconvenient to check this before 35*6777b538SAndroid Build Coastguard Worker // constructing the AutoReset object (e.g. in a class member initializer 36*6777b538SAndroid Build Coastguard Worker // list). 37*6777b538SAndroid Build Coastguard Worker template <typename U> AutoReset(T * scoped_variable,U && new_value,const T & expected_old_value)38*6777b538SAndroid Build Coastguard Worker AutoReset(T* scoped_variable, U&& new_value, const T& expected_old_value) 39*6777b538SAndroid Build Coastguard Worker : AutoReset(scoped_variable, new_value) { 40*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(original_value_, expected_old_value); 41*6777b538SAndroid Build Coastguard Worker } 42*6777b538SAndroid Build Coastguard Worker AutoReset(AutoReset && other)43*6777b538SAndroid Build Coastguard Worker AutoReset(AutoReset&& other) 44*6777b538SAndroid Build Coastguard Worker : scoped_variable_(std::exchange(other.scoped_variable_, nullptr)), 45*6777b538SAndroid Build Coastguard Worker original_value_(std::move(other.original_value_)) {} 46*6777b538SAndroid Build Coastguard Worker 47*6777b538SAndroid Build Coastguard Worker AutoReset& operator=(AutoReset&& rhs) { 48*6777b538SAndroid Build Coastguard Worker scoped_variable_ = std::exchange(rhs.scoped_variable_, nullptr); 49*6777b538SAndroid Build Coastguard Worker original_value_ = std::move(rhs.original_value_); 50*6777b538SAndroid Build Coastguard Worker return *this; 51*6777b538SAndroid Build Coastguard Worker } 52*6777b538SAndroid Build Coastguard Worker ~AutoReset()53*6777b538SAndroid Build Coastguard Worker ~AutoReset() { 54*6777b538SAndroid Build Coastguard Worker if (scoped_variable_) 55*6777b538SAndroid Build Coastguard Worker *scoped_variable_ = std::move(original_value_); 56*6777b538SAndroid Build Coastguard Worker } 57*6777b538SAndroid Build Coastguard Worker 58*6777b538SAndroid Build Coastguard Worker private: 59*6777b538SAndroid Build Coastguard Worker // `scoped_variable_` is not a raw_ptr<T> for performance reasons: Large 60*6777b538SAndroid Build Coastguard Worker // number of non-PartitionAlloc pointees + AutoReset is typically short-lived 61*6777b538SAndroid Build Coastguard Worker // (e.g. allocated on the stack). 62*6777b538SAndroid Build Coastguard Worker RAW_PTR_EXCLUSION T* scoped_variable_; 63*6777b538SAndroid Build Coastguard Worker 64*6777b538SAndroid Build Coastguard Worker T original_value_; 65*6777b538SAndroid Build Coastguard Worker }; 66*6777b538SAndroid Build Coastguard Worker 67*6777b538SAndroid Build Coastguard Worker } // namespace base 68*6777b538SAndroid Build Coastguard Worker 69*6777b538SAndroid Build Coastguard Worker #endif // BASE_AUTO_RESET_H_ 70