blob: cfd803b7d66855293654f34219694509fffb7fb4 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2011 The Chromium Authors
[email protected]5be7da242009-11-20 23:16:262// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_AUTO_RESET_H_
6#define BASE_AUTO_RESET_H_
7
Sam McNally54bc0282017-12-13 02:42:298#include <utility>
9
Peter Kasting0bca80f2023-03-07 04:37:5510#include "base/check_op.h"
Keishi Hattori488b7602022-05-02 13:09:3111#include "base/memory/raw_ptr_exclusion.h"
12
[email protected]997ec9f2012-11-21 04:44:1413// base::AutoReset<> is useful for setting a variable to a new value only within
14// a particular scope. An base::AutoReset<> object resets a variable to its
15// original value upon destruction, making it an alternative to writing
16// "var = false;" or "var = old_val;" at all of a block's exit points.
[email protected]5be7da242009-11-20 23:16:2617//
[email protected]997ec9f2012-11-21 04:44:1418// This should be obvious, but note that an base::AutoReset<> instance should
19// have a shorter lifetime than its scoped_variable, to prevent invalid memory
20// writes when the base::AutoReset<> object is destroyed.
21
22namespace base {
[email protected]5be7da242009-11-20 23:16:2623
Jan Wilken Dörriebcc12592019-10-11 18:26:5324template <typename T>
Peter Kastingb0bac5d2023-03-08 21:26:5625class [[maybe_unused, nodiscard]] AutoReset {
[email protected]5be7da242009-11-20 23:16:2626 public:
Jan Wilken Dörriebcc12592019-10-11 18:26:5327 template <typename U>
28 AutoReset(T* scoped_variable, U&& new_value)
[email protected]5be7da242009-11-20 23:16:2629 : scoped_variable_(scoped_variable),
Jan Wilken Dörriebcc12592019-10-11 18:26:5330 original_value_(
31 std::exchange(*scoped_variable_, std::forward<U>(new_value))) {}
[email protected]0fbd70332010-06-01 19:28:3432
Peter Kasting0bca80f2023-03-07 04:37:5533 // A constructor that's useful for asserting the old value of
34 // `scoped_variable`, especially when it's inconvenient to check this before
35 // constructing the AutoReset object (e.g. in a class member initializer
36 // list).
37 template <typename U>
38 AutoReset(T* scoped_variable, U&& new_value, const T& expected_old_value)
39 : AutoReset(scoped_variable, new_value) {
40 DCHECK_EQ(original_value_, expected_old_value);
41 }
42
Ahmed Fakhry3571b4f52019-05-15 20:55:4943 AutoReset(AutoReset&& other)
Jan Wilken Dörriebcc12592019-10-11 18:26:5344 : scoped_variable_(std::exchange(other.scoped_variable_, nullptr)),
45 original_value_(std::move(other.original_value_)) {}
46
47 AutoReset& operator=(AutoReset&& rhs) {
48 scoped_variable_ = std::exchange(rhs.scoped_variable_, nullptr);
49 original_value_ = std::move(rhs.original_value_);
50 return *this;
Ahmed Fakhry3571b4f52019-05-15 20:55:4951 }
52
53 ~AutoReset() {
Peter Kasting134ef9af2024-12-28 02:30:0954 if (scoped_variable_) {
Ahmed Fakhry3571b4f52019-05-15 20:55:4955 *scoped_variable_ = std::move(original_value_);
Peter Kasting134ef9af2024-12-28 02:30:0956 }
Ahmed Fakhry3571b4f52019-05-15 20:55:4957 }
58
[email protected]5be7da242009-11-20 23:16:2659 private:
Lukasz Anforowicz877e6222021-11-26 00:03:2360 // `scoped_variable_` is not a raw_ptr<T> for performance reasons: Large
61 // number of non-PartitionAlloc pointees + AutoReset is typically short-lived
62 // (e.g. allocated on the stack).
Keishi Hattori488b7602022-05-02 13:09:3163 RAW_PTR_EXCLUSION T* scoped_variable_;
Lukasz Anforowicz877e6222021-11-26 00:03:2364
[email protected]0fbd70332010-06-01 19:28:3465 T original_value_;
[email protected]5be7da242009-11-20 23:16:2666};
67
danakjc3762b92015-03-07 01:51:4268} // namespace base
[email protected]997ec9f2012-11-21 04:44:1469
[email protected]5be7da242009-11-20 23:16:2670#endif // BASE_AUTO_RESET_H_