1/* scoped_restore, a simple class for saving and restoring a value 2 3 Copyright (C) 2016-2024 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#ifndef COMMON_SCOPED_RESTORE_H 21#define COMMON_SCOPED_RESTORE_H 22 23/* Base class for scoped_restore_tmpl. */ 24class scoped_restore_base 25{ 26public: 27 /* This informs the (scoped_restore_tmpl<T>) dtor that you no longer 28 want the original value restored. */ 29 void release () const 30 { m_saved_var = NULL; } 31 32protected: 33 scoped_restore_base (void *saved_var) 34 : m_saved_var (saved_var) 35 {} 36 37 /* The type-erased saved variable. This is here so that clients can 38 call release() on a "scoped_restore" local, which is a typedef to 39 a scoped_restore_base. See below. */ 40 mutable void *m_saved_var; 41}; 42 43/* A convenience typedef. Users of make_scoped_restore declare the 44 local RAII object as having this type. */ 45typedef const scoped_restore_base &scoped_restore; 46 47/* An RAII-based object that saves a variable's value, and then 48 restores it again when this object is destroyed. */ 49template<typename T> 50class scoped_restore_tmpl : public scoped_restore_base 51{ 52 public: 53 54 /* Create a new scoped_restore object that saves the current value 55 of *VAR. *VAR will be restored when this scoped_restore object 56 is destroyed. */ 57 scoped_restore_tmpl (T *var) 58 : scoped_restore_base (var), 59 m_saved_value (*var) 60 { 61 } 62 63 /* Create a new scoped_restore object that saves the current value 64 of *VAR, and sets *VAR to VALUE. *VAR will be restored when this 65 scoped_restore object is destroyed. This is templated on T2 to 66 allow passing VALUEs of types convertible to T. 67 E.g.: T='base'; T2='derived'. */ 68 template <typename T2> 69 scoped_restore_tmpl (T *var, T2 value) 70 : scoped_restore_base (var), 71 m_saved_value (*var) 72 { 73 *var = value; 74 } 75 76 scoped_restore_tmpl (const scoped_restore_tmpl<T> &other) 77 : scoped_restore_base {other.m_saved_var}, 78 m_saved_value (other.m_saved_value) 79 { 80 other.m_saved_var = NULL; 81 } 82 83 ~scoped_restore_tmpl () 84 { 85 if (saved_var () != NULL) 86 *saved_var () = m_saved_value; 87 } 88 89private: 90 /* Return a pointer to the saved variable with its type 91 restored. */ 92 T *saved_var () 93 { return static_cast<T *> (m_saved_var); } 94 95 /* No need for this. It is intentionally not defined anywhere. */ 96 scoped_restore_tmpl &operator= (const scoped_restore_tmpl &); 97 98 /* The saved value. */ 99 const T m_saved_value; 100}; 101 102/* Make a scoped_restore. This is useful because it lets template 103 argument deduction work. */ 104template<typename T> 105scoped_restore_tmpl<T> make_scoped_restore (T *var) 106{ 107 return scoped_restore_tmpl<T> (var); 108} 109 110/* Make a scoped_restore. This is useful because it lets template 111 argument deduction work. */ 112template<typename T, typename T2> 113scoped_restore_tmpl<T> make_scoped_restore (T *var, T2 value) 114{ 115 return scoped_restore_tmpl<T> (var, value); 116} 117 118#endif /* COMMON_SCOPED_RESTORE_H */ 119