+class scoped_switch_fork_info
+{
+public:
+ /* Switch to the infrun state held on the fork_info identified by
+ PPTID. If PPTID is the current inferior then no switch is done. */
+ explicit scoped_switch_fork_info (ptid_t pptid)
+ : m_oldfp (nullptr)
+ {
+ if (pptid != inferior_ptid)
+ {
+ struct fork_info *newfp = nullptr;
+
+ /* Switch to pptid. */
+ m_oldfp = find_fork_ptid (inferior_ptid);
+ gdb_assert (m_oldfp != nullptr);
+ newfp = find_fork_ptid (pptid);
+ gdb_assert (newfp != nullptr);
+ fork_save_infrun_state (m_oldfp);
+ remove_breakpoints ();
+ fork_load_infrun_state (newfp);
+ insert_breakpoints ();
+ }
+ }
+
+ /* Restore the previously selected infrun state. If the constructor
+ didn't need to switch states, then nothing is done here either. */
+ ~scoped_switch_fork_info ()
+ {
+ if (m_oldfp != nullptr)
+ {
+ /* Switch back to inferior_ptid. */
+ try
+ {
+ remove_breakpoints ();
+ fork_load_infrun_state (m_oldfp);
+ insert_breakpoints ();
+ }
+ catch (const gdb_exception &ex)
+ {
+ warning (_("Couldn't restore checkpoint state in %s: %s"),
+ target_pid_to_str (m_oldfp->ptid).c_str (),
+ ex.what ());
+ }
+ }
+ }
+
+ DISABLE_COPY_AND_ASSIGN (scoped_switch_fork_info);
+
+private:
+ /* The fork_info for the previously selected infrun state, or nullptr if
+ we were already in the desired state, and nothing needs to be
+ restored. */
+ struct fork_info *m_oldfp;
+};