public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v2] Don't add window duplicates to tui_windows
       [not found] <20210105135549.5704-1-ssbssa.ref@yahoo.de>
@ 2021-01-05 13:55 ` Hannes Domani
  2021-01-25 16:18   ` Andrew Burgess
  0 siblings, 1 reply; 5+ messages in thread
From: Hannes Domani @ 2021-01-05 13:55 UTC (permalink / raw)
  To: gdb-patches

Otherwise, each time a window size is changed with 'winheight', all windows
are duplicated, and when done multiple times, slows down redrawing.

gdb/ChangeLog:

2021-01-05  Hannes Domani  <ssbssa@yahoo.de>

	* tui/tui-layout.c (tui_apply_current_layout): Add add_window
	argument to apply function.
	(tui_layout_window::apply): Likewise.
	(tui_layout_split::adjust_size): Likewise.
	(tui_layout_split::apply): Likewise.
	* tui/tui-layout.h (class tui_layout_base): Likewise.
	(class tui_layout_window): Likewise.
	(class tui_layout_split): Likewise.
---
v2:
- Use new add_window argument to decide if window should be added to
  tui_windows.
---
 gdb/tui/tui-layout.c | 19 ++++++++++++-------
 gdb/tui/tui-layout.h |  7 ++++---
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index d6e299b00f1..fc1b65d8799 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -85,7 +85,7 @@ tui_apply_current_layout ()
   for (tui_win_info *win_info : saved_tui_windows)
     win_info->make_visible (false);
 
-  applied_layout->apply (0, 0, tui_term_width (), tui_term_height ());
+  applied_layout->apply (0, 0, tui_term_width (), tui_term_height (), true);
 
   /* Keep the list of internal windows up-to-date.  */
   for (int win_type = SRC_WIN; (win_type < MAX_MAJOR_WINDOWS); win_type++)
@@ -416,7 +416,8 @@ tui_layout_window::clone () const
 /* See tui-layout.h.  */
 
 void
-tui_layout_window::apply (int x_, int y_, int width_, int height_)
+tui_layout_window::apply (int x_, int y_, int width_, int height_,
+			  bool add_window)
 {
   x = x_;
   y = y_;
@@ -424,7 +425,8 @@ tui_layout_window::apply (int x_, int y_, int width_, int height_)
   height = height_;
   gdb_assert (m_window != nullptr);
   m_window->resize (height, width, x, y);
-  tui_windows.push_back (m_window);
+  if (add_window)
+    tui_windows.push_back (m_window);
 }
 
 /* See tui-layout.h.  */
@@ -653,7 +655,7 @@ tui_layout_split::adjust_size (const char *name, int new_height)
   else
     {
       /* Simply re-apply the updated layout.  */
-      apply (x, y, width, height);
+      apply (x, y, width, height, false);
     }
 
   return HANDLED;
@@ -662,7 +664,8 @@ tui_layout_split::adjust_size (const char *name, int new_height)
 /* See tui-layout.h.  */
 
 void
-tui_layout_split::apply (int x_, int y_, int width_, int height_)
+tui_layout_split::apply (int x_, int y_, int width_, int height_,
+			 bool add_window)
 {
   x = x_;
   y = y_;
@@ -772,9 +775,11 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_)
       else if (info[i].share_box)
 	--size_accum;
       if (m_vertical)
-	m_splits[i].layout->apply (x, y + size_accum, width, info[i].size);
+	m_splits[i].layout->apply (x, y + size_accum, width, info[i].size,
+				   add_window);
       else
-	m_splits[i].layout->apply (x + size_accum, y, info[i].size, height);
+	m_splits[i].layout->apply (x + size_accum, y, info[i].size, height,
+				   add_window);
       size_accum += info[i].size;
     }
 
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index 193f42de420..7eb8ea911d3 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -56,7 +56,8 @@ class tui_layout_base
   virtual std::unique_ptr<tui_layout_base> clone () const = 0;
 
   /* Change the size and location of this layout.  */
-  virtual void apply (int x, int y, int width, int height) = 0;
+  virtual void apply (int x, int y, int width, int height,
+		      bool add_window) = 0;
 
   /* Return the minimum and maximum height or width of this layout.
      HEIGHT is true to fetch height, false to fetch width.  */
@@ -117,7 +118,7 @@ class tui_layout_window : public tui_layout_base
 
   std::unique_ptr<tui_layout_base> clone () const override;
 
-  void apply (int x, int y, int width, int height) override;
+  void apply (int x, int y, int width, int height, bool add_window) override;
 
   const char *get_name () const override
   {
@@ -181,7 +182,7 @@ class tui_layout_split : public tui_layout_base
 
   std::unique_ptr<tui_layout_base> clone () const override;
 
-  void apply (int x, int y, int width, int height) override;
+  void apply (int x, int y, int width, int height, bool add_window) override;
 
   tui_adjust_result adjust_size (const char *name, int new_height) override;
 
-- 
2.29.2


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] Don't add window duplicates to tui_windows
  2021-01-05 13:55 ` [PATCH v2] Don't add window duplicates to tui_windows Hannes Domani
@ 2021-01-25 16:18   ` Andrew Burgess
  2021-01-25 17:31     ` Hannes Domani
  2021-02-06 20:24     ` Tom Tromey
  0 siblings, 2 replies; 5+ messages in thread
From: Andrew Burgess @ 2021-01-25 16:18 UTC (permalink / raw)
  To: Hannes Domani; +Cc: gdb-patches, Tom Tromey

* Hannes Domani via Gdb-patches <gdb-patches@sourceware.org> [2021-01-05 14:55:49 +0100]:

> Otherwise, each time a window size is changed with 'winheight', all windows
> are duplicated, and when done multiple times, slows down redrawing.
> 
> gdb/ChangeLog:
> 
> 2021-01-05  Hannes Domani  <ssbssa@yahoo.de>
> 
> 	* tui/tui-layout.c (tui_apply_current_layout): Add add_window
> 	argument to apply function.
> 	(tui_layout_window::apply): Likewise.
> 	(tui_layout_split::adjust_size): Likewise.
> 	(tui_layout_split::apply): Likewise.
> 	* tui/tui-layout.h (class tui_layout_base): Likewise.
> 	(class tui_layout_window): Likewise.
> 	(class tui_layout_split): Likewise.
> ---
> v2:
> - Use new add_window argument to decide if window should be added to
>   tui_windows.
> ---
>  gdb/tui/tui-layout.c | 19 ++++++++++++-------
>  gdb/tui/tui-layout.h |  7 ++++---
>  2 files changed, 16 insertions(+), 10 deletions(-)
> 
> diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
> index d6e299b00f1..fc1b65d8799 100644
> --- a/gdb/tui/tui-layout.c
> +++ b/gdb/tui/tui-layout.c
> @@ -85,7 +85,7 @@ tui_apply_current_layout ()
>    for (tui_win_info *win_info : saved_tui_windows)
>      win_info->make_visible (false);
>  
> -  applied_layout->apply (0, 0, tui_term_width (), tui_term_height ());
> +  applied_layout->apply (0, 0, tui_term_width (), tui_term_height (), true);
>  
>    /* Keep the list of internal windows up-to-date.  */
>    for (int win_type = SRC_WIN; (win_type < MAX_MAJOR_WINDOWS); win_type++)
> @@ -416,7 +416,8 @@ tui_layout_window::clone () const
>  /* See tui-layout.h.  */
>  
>  void
> -tui_layout_window::apply (int x_, int y_, int width_, int height_)
> +tui_layout_window::apply (int x_, int y_, int width_, int height_,
> +			  bool add_window)
>  {
>    x = x_;
>    y = y_;
> @@ -424,7 +425,8 @@ tui_layout_window::apply (int x_, int y_, int width_, int height_)
>    height = height_;
>    gdb_assert (m_window != nullptr);
>    m_window->resize (height, width, x, y);
> -  tui_windows.push_back (m_window);
> +  if (add_window)
> +    tui_windows.push_back (m_window);
>  }

I wondered if there was a solution to this problem that would remove
the need to update some global state from the ::apply function.

I came up with the patch below.  What do you think?

This also includes a test that covers this issue, when I run the test
under valgrind it highlights that GDB tries to free the same object
multiple times.

Thanks,
Andrew


---

commit 3d47fcb70e234d08ab2e47c1527bca081846b8ee
Author: Andrew Burgess <andrew.burgess@embecosm.com>
Date:   Mon Jan 25 15:46:58 2021 +0000

    gdb/tui: don't add windows to global list from tui_layout:window::apply
    
    This commit was inspired by this mailing list patch:
    
      https://sourceware.org/pipermail/gdb-patches/2021-January/174713.html
    
    Currently, calling tui_layout_window::apply will add the window from
    the layout object to the global tui_windows list.
    
    Unfortunately, when the user runs the 'winheight' command, this calls
    tui_adjust_window_height, which calls the tui_layout_base::adjust_size
    function, which can then call tui_layout_base::apply.  The consequence
    of this is that when the user does 'winheight' duplicate copies of a
    window can be added to the global tui_windows list.
    
    The original patch fixed this by changing the apply function to only
    update the global list some of the time.
    
    This patch takes a different approach.  The apply function no longer
    updates the global tui_windows list.  Instead a new virtual function
    is added to tui_layout_base which is used to gather all the currently
    applied windows into a vector.  Finally tui_apply_current_layout is
    updated to make use of this new function to update the tui_windows
    list.
    
    The benefits I see in this approach are, (a) the apply function now no
    longer touches global state, this solves the immediate problem,
    and (b) now that tui_windows is updated directly in the function
    tui_apply_current_layout, we can drop the saved_tui_windows global.
    
    gdb/ChangeLog:
    
            * tui-layout.c (saved_tui_windows): Delete.
            (tui_apply_current_layout): Don't make use of saved_tui_windows,
            call new get_windows member function instead.
            (tui_get_window_by_name): Check in tui_windows.
            (tui_layout_window::apply): Don't add to tui_windows.
            * tui-layout.h (tui_layout_base::get_windows): New member function.
            (tui_layout_window::get_windows): Likewise.
            (tui_layout_split::get_windows): Likewise.
    
    gdb/testsuite/ChangeLog:
    
            * gdb.tui/winheight.exp: Add more tests.

diff --git a/gdb/testsuite/gdb.tui/winheight.exp b/gdb/testsuite/gdb.tui/winheight.exp
index 38fb29c3829..04de35d2f45 100644
--- a/gdb/testsuite/gdb.tui/winheight.exp
+++ b/gdb/testsuite/gdb.tui/winheight.exp
@@ -36,3 +36,17 @@ Term::check_box "smaller source box" 0 0 80 10
 
 Term::command "winheight cmd -5"
 Term::check_box "larger source box" 0 0 80 15
+
+Term::command "winheight src -5"
+Term::check_box "smaller source box again" 0 0 80 10
+
+Term::command "winheight src +5"
+Term::check_box "larger source box again" 0 0 80 15
+
+# At one point we had a bug where adjusting the winheight would result
+# in GDB keeping hold of duplicate window pointers, which it might
+# then try to delete when the layout was changed.  Running this test
+# under valgrind would expose that bug.
+Term::command "layout asm"
+Term::check_box "check for asm window" 0 0 80 15
+
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index d6e299b00f1..adb99852da2 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -64,11 +64,6 @@ static tui_layout_split *asm_regs_layout;
 /* See tui-data.h.  */
 std::vector<tui_win_info *> tui_windows;
 
-/* When applying a layout, this is the list of all windows that were
-   in the previous layout.  This is used to re-use windows when
-   changing a layout.  */
-static std::vector<tui_win_info *> saved_tui_windows;
-
 /* See tui-layout.h.  */
 
 void
@@ -79,10 +74,7 @@ tui_apply_current_layout ()
 
   extract_display_start_addr (&gdbarch, &addr);
 
-  saved_tui_windows = std::move (tui_windows);
-  tui_windows.clear ();
-
-  for (tui_win_info *win_info : saved_tui_windows)
+  for (tui_win_info *win_info : tui_windows)
     win_info->make_visible (false);
 
   applied_layout->apply (0, 0, tui_term_width (), tui_term_height ());
@@ -96,25 +88,33 @@ tui_apply_current_layout ()
   /* This should always be made visible by a layout.  */
   gdb_assert (TUI_CMD_WIN->is_visible ());
 
+  /* Get the new list of currently visible windows.  */
+  std::vector<tui_win_info *> new_tui_windows;
+  applied_layout->get_windows (&new_tui_windows);
+
   /* Now delete any window that was not re-applied.  */
   tui_win_info *focus = tui_win_with_focus ();
   tui_win_info *locator = tui_locator_win_info_ptr ();
-  for (tui_win_info *win_info : saved_tui_windows)
+  for (tui_win_info *win_info : tui_windows)
     {
       if (!win_info->is_visible ())
 	{
+	  /* If we're about to delete the window with focus then don't.
+	     This will be deleted later once we have selected an
+	     alternative window to focus on.  */
 	  if (focus == win_info)
-	    tui_set_win_focus_to (tui_windows[0]);
+	    tui_set_win_focus_to (new_tui_windows[0]);
 	  if (win_info != locator)
 	    delete win_info;
 	}
     }
 
+  tui_windows.clear ();
+  tui_windows = std::move (new_tui_windows);
+
   if (gdbarch == nullptr && TUI_DISASM_WIN != nullptr)
     tui_get_begin_asm_address (&gdbarch, &addr);
   tui_update_source_windows_with_addr (gdbarch, addr);
-
-  saved_tui_windows.clear ();
 }
 
 /* See tui-layout.  */
@@ -354,7 +354,7 @@ static std::unordered_map<std::string, window_factory> *known_window_types;
 static tui_win_info *
 tui_get_window_by_name (const std::string &name)
 {
-  for (tui_win_info *window : saved_tui_windows)
+  for (tui_win_info *window : tui_windows)
     if (name == window->name ())
       return window;
 
@@ -424,7 +424,6 @@ tui_layout_window::apply (int x_, int y_, int width_, int height_)
   height = height_;
   gdb_assert (m_window != nullptr);
   m_window->resize (height, width, x, y);
-  tui_windows.push_back (m_window);
 }
 
 /* See tui-layout.h.  */
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index 193f42de420..f89166eae37 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -91,6 +91,9 @@ class tui_layout_base
      depth of this layout in the hierarchy (zero-based).  */
   virtual void specification (ui_file *output, int depth) = 0;
 
+  /* Add all windows to the WINDOWS vector.  */
+  virtual void get_windows (std::vector<tui_win_info *> *windows) = 0;
+
   /* The most recent space allocation.  */
   int x = 0;
   int y = 0;
@@ -141,6 +144,12 @@ class tui_layout_window : public tui_layout_base
 
   void specification (ui_file *output, int depth) override;
 
+  /* See tui_layout_base::get_windows.  */
+  void get_windows (std::vector<tui_win_info *> *windows) override
+  {
+    windows->push_back (m_window);
+  }
+
 protected:
 
   void get_sizes (bool height, int *min_value, int *max_value) override;
@@ -195,6 +204,13 @@ class tui_layout_split : public tui_layout_base
 
   void specification (ui_file *output, int depth) override;
 
+  /* See tui_layout_base::get_windows.  */
+  void get_windows (std::vector<tui_win_info *> *windows) override
+  {
+    for (auto &item : m_splits)
+      item.layout->get_windows (windows);
+  }
+
 protected:
 
   void get_sizes (bool height, int *min_value, int *max_value) override;

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] Don't add window duplicates to tui_windows
  2021-01-25 16:18   ` Andrew Burgess
@ 2021-01-25 17:31     ` Hannes Domani
  2021-01-26  9:29       ` Andrew Burgess
  2021-02-06 20:24     ` Tom Tromey
  1 sibling, 1 reply; 5+ messages in thread
From: Hannes Domani @ 2021-01-25 17:31 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches, Tom Tromey

 Am Montag, 25. Januar 2021, 17:19:16 MEZ hat Andrew Burgess <andrew.burgess@embecosm.com> Folgendes geschrieben:

> * Hannes Domani via Gdb-patches <gdb-patches@sourceware.org> [2021-01-05 14:55:49 +0100]:
>
> > Otherwise, each time a window size is changed with 'winheight', all windows
> > are duplicated, and when done multiple times, slows down redrawing.
> >
> > gdb/ChangeLog:
> >
> > 2021-01-05  Hannes Domani  <ssbssa@yahoo.de>
> >
> >     * tui/tui-layout.c (tui_apply_current_layout): Add add_window
> >     argument to apply function.
> >     (tui_layout_window::apply): Likewise.
> >     (tui_layout_split::adjust_size): Likewise.
> >     (tui_layout_split::apply): Likewise.
> >     * tui/tui-layout.h (class tui_layout_base): Likewise.
> >     (class tui_layout_window): Likewise.
> >     (class tui_layout_split): Likewise.
> > ---
> > v2:
> > - Use new add_window argument to decide if window should be added to
> >  tui_windows.
> > ---
> >  gdb/tui/tui-layout.c | 19 ++++++++++++-------
> >  gdb/tui/tui-layout.h |  7 ++++---
> >  2 files changed, 16 insertions(+), 10 deletions(-)
> >
> > diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
> > index d6e299b00f1..fc1b65d8799 100644
> > --- a/gdb/tui/tui-layout.c
> > +++ b/gdb/tui/tui-layout.c
> > @@ -85,7 +85,7 @@ tui_apply_current_layout ()
> >    for (tui_win_info *win_info : saved_tui_windows)
> >      win_info->make_visible (false);
> >
> > -  applied_layout->apply (0, 0, tui_term_width (), tui_term_height ());
> > +  applied_layout->apply (0, 0, tui_term_width (), tui_term_height (), true);
> >
> >    /* Keep the list of internal windows up-to-date.  */
> >    for (int win_type = SRC_WIN; (win_type < MAX_MAJOR_WINDOWS); win_type++)
> > @@ -416,7 +416,8 @@ tui_layout_window::clone () const
> >  /* See tui-layout.h.  */
> >
> >  void
> > -tui_layout_window::apply (int x_, int y_, int width_, int height_)
> > +tui_layout_window::apply (int x_, int y_, int width_, int height_,
> > +              bool add_window)
> >  {
> >    x = x_;
> >    y = y_;
> > @@ -424,7 +425,8 @@ tui_layout_window::apply (int x_, int y_, int width_, int height_)
> >    height = height_;
> >    gdb_assert (m_window != nullptr);
> >    m_window->resize (height, width, x, y);
> > -  tui_windows.push_back (m_window);
> > +  if (add_window)
> > +    tui_windows.push_back (m_window);
> >  }
>
> I wondered if there was a solution to this problem that would remove
> the need to update some global state from the ::apply function.
>
> I came up with the patch below.  What do you think?

I think this is fine, I only have one question below.


> This also includes a test that covers this issue, when I run the test
> under valgrind it highlights that GDB tries to free the same object
> multiple times.
>
> Thanks,
> Andrew
>
>
> ---
>
> commit 3d47fcb70e234d08ab2e47c1527bca081846b8ee
> Author: Andrew Burgess <andrew.burgess@embecosm.com>
> Date:  Mon Jan 25 15:46:58 2021 +0000
>
>     gdb/tui: don't add windows to global list from tui_layout:window::apply
>    
>     This commit was inspired by this mailing list patch:
>    
>       https://sourceware.org/pipermail/gdb-patches/2021-January/174713.html
>    
>     Currently, calling tui_layout_window::apply will add the window from
>     the layout object to the global tui_windows list.
>    
>     Unfortunately, when the user runs the 'winheight' command, this calls
>     tui_adjust_window_height, which calls the tui_layout_base::adjust_size
>     function, which can then call tui_layout_base::apply.  The consequence
>     of this is that when the user does 'winheight' duplicate copies of a
>     window can be added to the global tui_windows list.
>    
>     The original patch fixed this by changing the apply function to only
>     update the global list some of the time.
>    
>     This patch takes a different approach.  The apply function no longer
>     updates the global tui_windows list.  Instead a new virtual function
>     is added to tui_layout_base which is used to gather all the currently
>     applied windows into a vector.  Finally tui_apply_current_layout is
>     updated to make use of this new function to update the tui_windows
>     list.
>    
>     The benefits I see in this approach are, (a) the apply function now no
>     longer touches global state, this solves the immediate problem,
>     and (b) now that tui_windows is updated directly in the function
>     tui_apply_current_layout, we can drop the saved_tui_windows global.
>    
>     gdb/ChangeLog:
>    
>             * tui-layout.c (saved_tui_windows): Delete.
>             (tui_apply_current_layout): Don't make use of saved_tui_windows,
>             call new get_windows member function instead.
>             (tui_get_window_by_name): Check in tui_windows.
>             (tui_layout_window::apply): Don't add to tui_windows.
>             * tui-layout.h (tui_layout_base::get_windows): New member function.
>             (tui_layout_window::get_windows): Likewise.
>             (tui_layout_split::get_windows): Likewise.
>    
>     gdb/testsuite/ChangeLog:
>    
>             * gdb.tui/winheight.exp: Add more tests.
>
> diff --git a/gdb/testsuite/gdb.tui/winheight.exp b/gdb/testsuite/gdb.tui/winheight.exp
> index 38fb29c3829..04de35d2f45 100644
> --- a/gdb/testsuite/gdb.tui/winheight.exp
> +++ b/gdb/testsuite/gdb.tui/winheight.exp
> @@ -36,3 +36,17 @@ Term::check_box "smaller source box" 0 0 80 10
>
> Term::command "winheight cmd -5"
> Term::check_box "larger source box" 0 0 80 15
> +
> +Term::command "winheight src -5"
> +Term::check_box "smaller source box again" 0 0 80 10
> +
> +Term::command "winheight src +5"
> +Term::check_box "larger source box again" 0 0 80 15
> +
> +# At one point we had a bug where adjusting the winheight would result
> +# in GDB keeping hold of duplicate window pointers, which it might
> +# then try to delete when the layout was changed.  Running this test
> +# under valgrind would expose that bug.
> +Term::command "layout asm"
> +Term::check_box "check for asm window" 0 0 80 15
> +
> diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
> index d6e299b00f1..adb99852da2 100644
> --- a/gdb/tui/tui-layout.c
> +++ b/gdb/tui/tui-layout.c
> @@ -64,11 +64,6 @@ static tui_layout_split *asm_regs_layout;
> /* See tui-data.h.  */
> std::vector<tui_win_info *> tui_windows;
>
> -/* When applying a layout, this is the list of all windows that were
> -  in the previous layout.  This is used to re-use windows when
> -  changing a layout.  */
> -static std::vector<tui_win_info *> saved_tui_windows;
> -
> /* See tui-layout.h.  */
>
> void
> @@ -79,10 +74,7 @@ tui_apply_current_layout ()
>
>   extract_display_start_addr (&gdbarch, &addr);
>
> -  saved_tui_windows = std::move (tui_windows);
> -  tui_windows.clear ();
> -
> -  for (tui_win_info *win_info : saved_tui_windows)
> +  for (tui_win_info *win_info : tui_windows)
>     win_info->make_visible (false);
>
>   applied_layout->apply (0, 0, tui_term_width (), tui_term_height ());
> @@ -96,25 +88,33 @@ tui_apply_current_layout ()
>   /* This should always be made visible by a layout.  */
>   gdb_assert (TUI_CMD_WIN->is_visible ());
>
> +  /* Get the new list of currently visible windows.  */
> +  std::vector<tui_win_info *> new_tui_windows;
> +  applied_layout->get_windows (&new_tui_windows);
> +
>   /* Now delete any window that was not re-applied.  */
>   tui_win_info *focus = tui_win_with_focus ();
>   tui_win_info *locator = tui_locator_win_info_ptr ();
> -  for (tui_win_info *win_info : saved_tui_windows)
> +  for (tui_win_info *win_info : tui_windows)
>     {
>       if (!win_info->is_visible ())
>     {
> +      /* If we're about to delete the window with focus then don't.
> +        This will be deleted later once we have selected an
> +        alternative window to focus on.  */
>       if (focus == win_info)
> -        tui_set_win_focus_to (tui_windows[0]);
> +        tui_set_win_focus_to (new_tui_windows[0]);
>       if (win_info != locator)
>         delete win_info;
>     }
>     }
>
> +  tui_windows.clear ();

Isn't this clear() redundant?


> +  tui_windows = std::move (new_tui_windows);
> +
>   if (gdbarch == nullptr && TUI_DISASM_WIN != nullptr)
>     tui_get_begin_asm_address (&gdbarch, &addr);
>   tui_update_source_windows_with_addr (gdbarch, addr);
> -
> -  saved_tui_windows.clear ();
> }
>
> /* See tui-layout.  */
> @@ -354,7 +354,7 @@ static std::unordered_map<std::string, window_factory> *known_window_types;
> static tui_win_info *
> tui_get_window_by_name (const std::string &name)
> {
> -  for (tui_win_info *window : saved_tui_windows)
> +  for (tui_win_info *window : tui_windows)
>     if (name == window->name ())
>       return window;
>
> @@ -424,7 +424,6 @@ tui_layout_window::apply (int x_, int y_, int width_, int height_)
>   height = height_;
>   gdb_assert (m_window != nullptr);
>   m_window->resize (height, width, x, y);
> -  tui_windows.push_back (m_window);
> }
>
> /* See tui-layout.h.  */
> diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
> index 193f42de420..f89166eae37 100644
> --- a/gdb/tui/tui-layout.h
> +++ b/gdb/tui/tui-layout.h
> @@ -91,6 +91,9 @@ class tui_layout_base
>       depth of this layout in the hierarchy (zero-based).  */
>   virtual void specification (ui_file *output, int depth) = 0;
>
> +  /* Add all windows to the WINDOWS vector.  */
> +  virtual void get_windows (std::vector<tui_win_info *> *windows) = 0;
> +
>   /* The most recent space allocation.  */
>   int x = 0;
>   int y = 0;
> @@ -141,6 +144,12 @@ class tui_layout_window : public tui_layout_base
>
>   void specification (ui_file *output, int depth) override;
>
> +  /* See tui_layout_base::get_windows.  */
> +  void get_windows (std::vector<tui_win_info *> *windows) override
> +  {
> +    windows->push_back (m_window);
> +  }
> +
> protected:
>
>   void get_sizes (bool height, int *min_value, int *max_value) override;
> @@ -195,6 +204,13 @@ class tui_layout_split : public tui_layout_base
>
>   void specification (ui_file *output, int depth) override;
>
> +  /* See tui_layout_base::get_windows.  */
> +  void get_windows (std::vector<tui_win_info *> *windows) override
> +  {
> +    for (auto &item : m_splits)
> +      item.layout->get_windows (windows);
> +  }
> +
> protected:
>
>   void get_sizes (bool height, int *min_value, int *max_value) override;

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] Don't add window duplicates to tui_windows
  2021-01-25 17:31     ` Hannes Domani
@ 2021-01-26  9:29       ` Andrew Burgess
  0 siblings, 0 replies; 5+ messages in thread
From: Andrew Burgess @ 2021-01-26  9:29 UTC (permalink / raw)
  To: Hannes Domani; +Cc: gdb-patches, Tom Tromey

* Hannes Domani <ssbssa@yahoo.de> [2021-01-25 17:31:35 +0000]:

>  Am Montag, 25. Januar 2021, 17:19:16 MEZ hat Andrew Burgess <andrew.burgess@embecosm.com> Folgendes geschrieben:
> 
> > * Hannes Domani via Gdb-patches <gdb-patches@sourceware.org> [2021-01-05 14:55:49 +0100]:
> >
> > > Otherwise, each time a window size is changed with 'winheight', all windows
> > > are duplicated, and when done multiple times, slows down redrawing.
> > >
> > > gdb/ChangeLog:
> > >
> > > 2021-01-05  Hannes Domani  <ssbssa@yahoo.de>
> > >
> > >     * tui/tui-layout.c (tui_apply_current_layout): Add add_window
> > >     argument to apply function.
> > >     (tui_layout_window::apply): Likewise.
> > >     (tui_layout_split::adjust_size): Likewise.
> > >     (tui_layout_split::apply): Likewise.
> > >     * tui/tui-layout.h (class tui_layout_base): Likewise.
> > >     (class tui_layout_window): Likewise.
> > >     (class tui_layout_split): Likewise.
> > > ---
> > > v2:
> > > - Use new add_window argument to decide if window should be added to
> > >  tui_windows.
> > > ---
> > >  gdb/tui/tui-layout.c | 19 ++++++++++++-------
> > >  gdb/tui/tui-layout.h |  7 ++++---
> > >  2 files changed, 16 insertions(+), 10 deletions(-)
> > >
> > > diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
> > > index d6e299b00f1..fc1b65d8799 100644
> > > --- a/gdb/tui/tui-layout.c
> > > +++ b/gdb/tui/tui-layout.c
> > > @@ -85,7 +85,7 @@ tui_apply_current_layout ()
> > >    for (tui_win_info *win_info : saved_tui_windows)
> > >      win_info->make_visible (false);
> > >
> > > -  applied_layout->apply (0, 0, tui_term_width (), tui_term_height ());
> > > +  applied_layout->apply (0, 0, tui_term_width (), tui_term_height (), true);
> > >
> > >    /* Keep the list of internal windows up-to-date.  */
> > >    for (int win_type = SRC_WIN; (win_type < MAX_MAJOR_WINDOWS); win_type++)
> > > @@ -416,7 +416,8 @@ tui_layout_window::clone () const
> > >  /* See tui-layout.h.  */
> > >
> > >  void
> > > -tui_layout_window::apply (int x_, int y_, int width_, int height_)
> > > +tui_layout_window::apply (int x_, int y_, int width_, int height_,
> > > +              bool add_window)
> > >  {
> > >    x = x_;
> > >    y = y_;
> > > @@ -424,7 +425,8 @@ tui_layout_window::apply (int x_, int y_, int width_, int height_)
> > >    height = height_;
> > >    gdb_assert (m_window != nullptr);
> > >    m_window->resize (height, width, x, y);
> > > -  tui_windows.push_back (m_window);
> > > +  if (add_window)
> > > +    tui_windows.push_back (m_window);
> > >  }
> >
> > I wondered if there was a solution to this problem that would remove
> > the need to update some global state from the ::apply function.
> >
> > I came up with the patch below.  What do you think?
> 
> I think this is fine, I only have one question below.
> 
> 
> > This also includes a test that covers this issue, when I run the test
> > under valgrind it highlights that GDB tries to free the same object
> > multiple times.
> >
> > Thanks,
> > Andrew
> >
> >
> > ---
> >
> > commit 3d47fcb70e234d08ab2e47c1527bca081846b8ee
> > Author: Andrew Burgess <andrew.burgess@embecosm.com>
> > Date:  Mon Jan 25 15:46:58 2021 +0000
> >
> >     gdb/tui: don't add windows to global list from tui_layout:window::apply
> >    
> >     This commit was inspired by this mailing list patch:
> >    
> >       https://sourceware.org/pipermail/gdb-patches/2021-January/174713.html
> >    
> >     Currently, calling tui_layout_window::apply will add the window from
> >     the layout object to the global tui_windows list.
> >    
> >     Unfortunately, when the user runs the 'winheight' command, this calls
> >     tui_adjust_window_height, which calls the tui_layout_base::adjust_size
> >     function, which can then call tui_layout_base::apply.  The consequence
> >     of this is that when the user does 'winheight' duplicate copies of a
> >     window can be added to the global tui_windows list.
> >    
> >     The original patch fixed this by changing the apply function to only
> >     update the global list some of the time.
> >    
> >     This patch takes a different approach.  The apply function no longer
> >     updates the global tui_windows list.  Instead a new virtual function
> >     is added to tui_layout_base which is used to gather all the currently
> >     applied windows into a vector.  Finally tui_apply_current_layout is
> >     updated to make use of this new function to update the tui_windows
> >     list.
> >    
> >     The benefits I see in this approach are, (a) the apply function now no
> >     longer touches global state, this solves the immediate problem,
> >     and (b) now that tui_windows is updated directly in the function
> >     tui_apply_current_layout, we can drop the saved_tui_windows global.
> >    
> >     gdb/ChangeLog:
> >    
> >             * tui-layout.c (saved_tui_windows): Delete.
> >             (tui_apply_current_layout): Don't make use of saved_tui_windows,
> >             call new get_windows member function instead.
> >             (tui_get_window_by_name): Check in tui_windows.
> >             (tui_layout_window::apply): Don't add to tui_windows.
> >             * tui-layout.h (tui_layout_base::get_windows): New member function.
> >             (tui_layout_window::get_windows): Likewise.
> >             (tui_layout_split::get_windows): Likewise.
> >    
> >     gdb/testsuite/ChangeLog:
> >    
> >             * gdb.tui/winheight.exp: Add more tests.
> >
> > diff --git a/gdb/testsuite/gdb.tui/winheight.exp b/gdb/testsuite/gdb.tui/winheight.exp
> > index 38fb29c3829..04de35d2f45 100644
> > --- a/gdb/testsuite/gdb.tui/winheight.exp
> > +++ b/gdb/testsuite/gdb.tui/winheight.exp
> > @@ -36,3 +36,17 @@ Term::check_box "smaller source box" 0 0 80 10
> >
> > Term::command "winheight cmd -5"
> > Term::check_box "larger source box" 0 0 80 15
> > +
> > +Term::command "winheight src -5"
> > +Term::check_box "smaller source box again" 0 0 80 10
> > +
> > +Term::command "winheight src +5"
> > +Term::check_box "larger source box again" 0 0 80 15
> > +
> > +# At one point we had a bug where adjusting the winheight would result
> > +# in GDB keeping hold of duplicate window pointers, which it might
> > +# then try to delete when the layout was changed.  Running this test
> > +# under valgrind would expose that bug.
> > +Term::command "layout asm"
> > +Term::check_box "check for asm window" 0 0 80 15
> > +
> > diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
> > index d6e299b00f1..adb99852da2 100644
> > --- a/gdb/tui/tui-layout.c
> > +++ b/gdb/tui/tui-layout.c
> > @@ -64,11 +64,6 @@ static tui_layout_split *asm_regs_layout;
> > /* See tui-data.h.  */
> > std::vector<tui_win_info *> tui_windows;
> >
> > -/* When applying a layout, this is the list of all windows that were
> > -  in the previous layout.  This is used to re-use windows when
> > -  changing a layout.  */
> > -static std::vector<tui_win_info *> saved_tui_windows;
> > -
> > /* See tui-layout.h.  */
> >
> > void
> > @@ -79,10 +74,7 @@ tui_apply_current_layout ()
> >
> >   extract_display_start_addr (&gdbarch, &addr);
> >
> > -  saved_tui_windows = std::move (tui_windows);
> > -  tui_windows.clear ();
> > -
> > -  for (tui_win_info *win_info : saved_tui_windows)
> > +  for (tui_win_info *win_info : tui_windows)
> >     win_info->make_visible (false);
> >
> >   applied_layout->apply (0, 0, tui_term_width (), tui_term_height ());
> > @@ -96,25 +88,33 @@ tui_apply_current_layout ()
> >   /* This should always be made visible by a layout.  */
> >   gdb_assert (TUI_CMD_WIN->is_visible ());
> >
> > +  /* Get the new list of currently visible windows.  */
> > +  std::vector<tui_win_info *> new_tui_windows;
> > +  applied_layout->get_windows (&new_tui_windows);
> > +
> >   /* Now delete any window that was not re-applied.  */
> >   tui_win_info *focus = tui_win_with_focus ();
> >   tui_win_info *locator = tui_locator_win_info_ptr ();
> > -  for (tui_win_info *win_info : saved_tui_windows)
> > +  for (tui_win_info *win_info : tui_windows)
> >     {
> >       if (!win_info->is_visible ())
> >     {
> > +      /* If we're about to delete the window with focus then don't.
> > +        This will be deleted later once we have selected an
> > +        alternative window to focus on.  */
> >       if (focus == win_info)
> > -        tui_set_win_focus_to (tui_windows[0]);
> > +        tui_set_win_focus_to (new_tui_windows[0]);
> >       if (win_info != locator)
> >         delete win_info;
> >     }
> >     }
> >
> > +  tui_windows.clear ();
> 
> Isn't this clear() redundant?

Good catch, I'll drop that from the change.

Thanks,
Andrew



> 
> 
> > +  tui_windows = std::move (new_tui_windows);
> > +
> >   if (gdbarch == nullptr && TUI_DISASM_WIN != nullptr)
> >     tui_get_begin_asm_address (&gdbarch, &addr);
> >   tui_update_source_windows_with_addr (gdbarch, addr);
> > -
> > -  saved_tui_windows.clear ();
> > }
> >
> > /* See tui-layout.  */
> > @@ -354,7 +354,7 @@ static std::unordered_map<std::string, window_factory> *known_window_types;
> > static tui_win_info *
> > tui_get_window_by_name (const std::string &name)
> > {
> > -  for (tui_win_info *window : saved_tui_windows)
> > +  for (tui_win_info *window : tui_windows)
> >     if (name == window->name ())
> >       return window;
> >
> > @@ -424,7 +424,6 @@ tui_layout_window::apply (int x_, int y_, int width_, int height_)
> >   height = height_;
> >   gdb_assert (m_window != nullptr);
> >   m_window->resize (height, width, x, y);
> > -  tui_windows.push_back (m_window);
> > }
> >
> > /* See tui-layout.h.  */
> > diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
> > index 193f42de420..f89166eae37 100644
> > --- a/gdb/tui/tui-layout.h
> > +++ b/gdb/tui/tui-layout.h
> > @@ -91,6 +91,9 @@ class tui_layout_base
> >       depth of this layout in the hierarchy (zero-based).  */
> >   virtual void specification (ui_file *output, int depth) = 0;
> >
> > +  /* Add all windows to the WINDOWS vector.  */
> > +  virtual void get_windows (std::vector<tui_win_info *> *windows) = 0;
> > +
> >   /* The most recent space allocation.  */
> >   int x = 0;
> >   int y = 0;
> > @@ -141,6 +144,12 @@ class tui_layout_window : public tui_layout_base
> >
> >   void specification (ui_file *output, int depth) override;
> >
> > +  /* See tui_layout_base::get_windows.  */
> > +  void get_windows (std::vector<tui_win_info *> *windows) override
> > +  {
> > +    windows->push_back (m_window);
> > +  }
> > +
> > protected:
> >
> >   void get_sizes (bool height, int *min_value, int *max_value) override;
> > @@ -195,6 +204,13 @@ class tui_layout_split : public tui_layout_base
> >
> >   void specification (ui_file *output, int depth) override;
> >
> > +  /* See tui_layout_base::get_windows.  */
> > +  void get_windows (std::vector<tui_win_info *> *windows) override
> > +  {
> > +    for (auto &item : m_splits)
> > +      item.layout->get_windows (windows);
> > +  }
> > +
> > protected:
> >
> >   void get_sizes (bool height, int *min_value, int *max_value) override;

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] Don't add window duplicates to tui_windows
  2021-01-25 16:18   ` Andrew Burgess
  2021-01-25 17:31     ` Hannes Domani
@ 2021-02-06 20:24     ` Tom Tromey
  1 sibling, 0 replies; 5+ messages in thread
From: Tom Tromey @ 2021-02-06 20:24 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: Hannes Domani, Tom Tromey, gdb-patches

>>>>> "Andrew" == Andrew Burgess <andrew.burgess@embecosm.com> writes:

Andrew> I wondered if there was a solution to this problem that would remove
Andrew> the need to update some global state from the ::apply function.

This seems like a good idea.  Thank you for doing this.

Tom

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-02-06 20:25 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20210105135549.5704-1-ssbssa.ref@yahoo.de>
2021-01-05 13:55 ` [PATCH v2] Don't add window duplicates to tui_windows Hannes Domani
2021-01-25 16:18   ` Andrew Burgess
2021-01-25 17:31     ` Hannes Domani
2021-01-26  9:29       ` Andrew Burgess
2021-02-06 20:24     ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).