xref: /aosp_15_r20/external/cronet/base/auto_reset.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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