summaryrefslogtreecommitdiff
path: root/gdbsupport/scoped_restore.h
diff options
context:
space:
mode:
Diffstat (limited to 'gdbsupport/scoped_restore.h')
-rw-r--r--gdbsupport/scoped_restore.h118
1 files changed, 118 insertions, 0 deletions
diff --git a/gdbsupport/scoped_restore.h b/gdbsupport/scoped_restore.h
new file mode 100644
index 00000000000..0dca6d06dbc
--- /dev/null
+++ b/gdbsupport/scoped_restore.h
@@ -0,0 +1,118 @@
+/* scoped_restore, a simple class for saving and restoring a value
+
+ Copyright (C) 2016-2020 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef COMMON_SCOPED_RESTORE_H
+#define COMMON_SCOPED_RESTORE_H
+
+/* Base class for scoped_restore_tmpl. */
+class scoped_restore_base
+{
+public:
+ /* This informs the (scoped_restore_tmpl<T>) dtor that you no longer
+ want the original value restored. */
+ void release () const
+ { m_saved_var = NULL; }
+
+protected:
+ scoped_restore_base (void *saved_var)
+ : m_saved_var (saved_var)
+ {}
+
+ /* The type-erased saved variable. This is here so that clients can
+ call release() on a "scoped_restore" local, which is a typedef to
+ a scoped_restore_base. See below. */
+ mutable void *m_saved_var;
+};
+
+/* A convenience typedef. Users of make_scoped_restore declare the
+ local RAII object as having this type. */
+typedef const scoped_restore_base &scoped_restore;
+
+/* An RAII-based object that saves a variable's value, and then
+ restores it again when this object is destroyed. */
+template<typename T>
+class scoped_restore_tmpl : public scoped_restore_base
+{
+ public:
+
+ /* Create a new scoped_restore object that saves the current value
+ of *VAR. *VAR will be restored when this scoped_restore object
+ is destroyed. */
+ scoped_restore_tmpl (T *var)
+ : scoped_restore_base (var),
+ m_saved_value (*var)
+ {
+ }
+
+ /* Create a new scoped_restore object that saves the current value
+ of *VAR, and sets *VAR to VALUE. *VAR will be restored when this
+ scoped_restore object is destroyed. This is templated on T2 to
+ allow passing VALUEs of types convertible to T.
+ E.g.: T='base'; T2='derived'. */
+ template <typename T2>
+ scoped_restore_tmpl (T *var, T2 value)
+ : scoped_restore_base (var),
+ m_saved_value (*var)
+ {
+ *var = value;
+ }
+
+ scoped_restore_tmpl (const scoped_restore_tmpl<T> &other)
+ : scoped_restore_base {other.m_saved_var},
+ m_saved_value (other.m_saved_value)
+ {
+ other.m_saved_var = NULL;
+ }
+
+ ~scoped_restore_tmpl ()
+ {
+ if (saved_var () != NULL)
+ *saved_var () = m_saved_value;
+ }
+
+private:
+ /* Return a pointer to the saved variable with its type
+ restored. */
+ T *saved_var ()
+ { return static_cast<T *> (m_saved_var); }
+
+ /* No need for this. It is intentionally not defined anywhere. */
+ scoped_restore_tmpl &operator= (const scoped_restore_tmpl &);
+
+ /* The saved value. */
+ const T m_saved_value;
+};
+
+/* Make a scoped_restore. This is useful because it lets template
+ argument deduction work. */
+template<typename T>
+scoped_restore_tmpl<T> make_scoped_restore (T *var)
+{
+ return scoped_restore_tmpl<T> (var);
+}
+
+/* Make a scoped_restore. This is useful because it lets template
+ argument deduction work. */
+template<typename T, typename T2>
+scoped_restore_tmpl<T> make_scoped_restore (T *var, T2 value)
+{
+ return scoped_restore_tmpl<T> (var, value);
+}
+
+#endif /* COMMON_SCOPED_RESTORE_H */