This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 3/8] C++fy thread_apply_all_command


This eliminates a couple cleanups.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* thread.c: Include <algorithm>.
	(thread_array_cleanup): Delete.
	(scoped_inc_dec_ref): New class.
	(live_threads_count): New function.
	(set_thread_refcount): Delete.
	(tp_array_compar_ascending): Now a bool.
	(tp_array_compar): Convert to a std::sort comparison function.
	(thread_apply_all_command): Use std::vector and scoped_inc_dec_ref
	and live_threads_count.
---
 gdb/thread.c | 137 +++++++++++++++++++++++++++++++----------------------------
 1 file changed, 73 insertions(+), 64 deletions(-)

diff --git a/gdb/thread.c b/gdb/thread.c
index abfce71..88fd521 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -44,6 +44,7 @@
 #include "cli/cli-utils.h"
 #include "thread-fsm.h"
 #include "tid-parse.h"
+#include <algorithm>
 
 /* Definition of struct thread_info exported to gdbthread.h.  */
 
@@ -69,16 +70,27 @@ static void info_threads_command (char *, int);
 static void thread_apply_command (char *, int);
 static void restore_current_thread (ptid_t);
 
-/* Data to cleanup thread array.  */
+/* RAII type used to increase / decrease the refcount of each thread
+   in a given list of threads.  */
 
-struct thread_array_cleanup
+class scoped_inc_dec_ref
 {
-  /* Array of thread pointers used to set
-     reference count.  */
-  struct thread_info **tp_array;
+public:
+  explicit scoped_inc_dec_ref (const std::vector<thread_info *> &thrds)
+    : m_thrds (thrds)
+  {
+    for (thread_info *thr : m_thrds)
+      thr->incref ();
+  }
 
-  /* Thread count in the array.  */
-  int count;
+  ~scoped_inc_dec_ref ()
+  {
+    for (thread_info *thr : m_thrds)
+      thr->decref ();
+  }
+
+private:
+  const std::vector<thread_info *> &m_thrds;
 };
 
 
@@ -565,6 +577,20 @@ thread_count (void)
   return result;
 }
 
+/* Return the number of non-exited threads in the thread list.  */
+
+static int
+live_threads_count (void)
+{
+  int result = 0;
+  struct thread_info *tp;
+
+  ALL_NON_EXITED_THREADS (tp)
+    ++result;
+
+  return result;
+}
+
 int
 valid_global_thread_id (int global_id)
 {
@@ -1605,19 +1631,6 @@ restore_current_thread_cleanup_dtor (void *arg)
   xfree (old);
 }
 
-/* Set the thread reference count.  */
-
-static void
-set_thread_refcount (void *data)
-{
-  int k;
-  struct thread_array_cleanup *ta_cleanup
-    = (struct thread_array_cleanup *) data;
-
-  for (k = 0; k != ta_cleanup->count; k++)
-    ta_cleanup->tp_array[k]->decref ();
-}
-
 struct cleanup *
 make_cleanup_restore_current_thread (void)
 {
@@ -1693,30 +1706,30 @@ print_thread_id (struct thread_info *thr)
   return s;
 }
 
-/* If non-zero tp_array_compar should sort in ascending order, otherwise in
-   descending order.  */
+/* If true, tp_array_compar should sort in ascending order, otherwise
+   in descending order.  */
 
-static int tp_array_compar_ascending;
+static bool tp_array_compar_ascending;
 
 /* Sort an array for struct thread_info pointers by thread ID (first
    by inferior number, and then by per-inferior thread number).  The
    order is determined by TP_ARRAY_COMPAR_ASCENDING.  */
 
-static int
-tp_array_compar (const void *ap_voidp, const void *bp_voidp)
+static bool
+tp_array_compar (const thread_info *a, const thread_info *b)
 {
-  const struct thread_info *a = *(const struct thread_info * const *) ap_voidp;
-  const struct thread_info *b = *(const struct thread_info * const *) bp_voidp;
-
   if (a->inf->num != b->inf->num)
     {
-      return (((a->inf->num > b->inf->num) - (a->inf->num < b->inf->num))
-	      * (tp_array_compar_ascending ? +1 : -1));
+      if (tp_array_compar_ascending)
+	return a->inf->num < b->inf->num;
+      else
+	return a->inf->num > b->inf->num;
     }
 
-  return (((a->per_inf_num > b->per_inf_num)
-	   - (a->per_inf_num < b->per_inf_num))
-	  * (tp_array_compar_ascending ? +1 : -1));
+  if (tp_array_compar_ascending)
+    return (a->per_inf_num < b->per_inf_num);
+  else
+    return (a->per_inf_num > b->per_inf_num);
 }
 
 /* Apply a GDB command to a list of threads.  List syntax is a whitespace
@@ -1732,15 +1745,13 @@ thread_apply_all_command (char *cmd, int from_tty)
 {
   struct cleanup *old_chain;
   char *saved_cmd;
-  int tc;
-  struct thread_array_cleanup ta_cleanup;
 
-  tp_array_compar_ascending = 0;
+  tp_array_compar_ascending = false;
   if (cmd != NULL
       && check_for_argument (&cmd, "-ascending", strlen ("-ascending")))
     {
       cmd = skip_spaces (cmd);
-      tp_array_compar_ascending = 1;
+      tp_array_compar_ascending = true;
     }
 
   if (cmd == NULL || *cmd == '\000')
@@ -1755,42 +1766,40 @@ thread_apply_all_command (char *cmd, int from_tty)
   saved_cmd = xstrdup (cmd);
   make_cleanup (xfree, saved_cmd);
 
-  /* Note this includes exited threads.  */
-  tc = thread_count ();
+  int tc = live_threads_count ();
   if (tc != 0)
     {
-      struct thread_info **tp_array;
-      struct thread_info *tp;
-      int i = 0, k;
+      /* Save a copy of the thread list and increment each thread's
+	 refcount while executing the command in the context of each
+	 thread, in case the command is one that wipes threads.  E.g.,
+	 detach, kill, disconnect, etc., or even normally continuing
+	 over an inferior or thread exit.  */
+      std::vector<thread_info *> thr_list_cpy;
+      thr_list_cpy.reserve (tc);
 
-      /* Save a copy of the thread_list in case we execute detach
-	 command.  */
-      tp_array = XNEWVEC (struct thread_info *, tc);
-      make_cleanup (xfree, tp_array);
+      {
+	thread_info *tp;
 
-      ALL_NON_EXITED_THREADS (tp)
-	{
-	  tp_array[i] = tp;
-	  tp->incref ();
-	  i++;
-	}
-      /* Because we skipped exited threads, we may end up with fewer
-	 threads in the array than the total count of threads.  */
-      gdb_assert (i <= tc);
+	ALL_NON_EXITED_THREADS (tp)
+	  {
+	    thr_list_cpy.push_back (tp);
+	  }
+
+	gdb_assert (thr_list_cpy.size () == tc);
+      }
 
-      if (i != 0)
-	qsort (tp_array, i, sizeof (*tp_array), tp_array_compar);
+      /* Increment the refcounts, and restore them back on scope
+	 exit.  */
+      scoped_inc_dec_ref inc_dec_ref (thr_list_cpy);
 
-      ta_cleanup.tp_array = tp_array;
-      ta_cleanup.count = i;
-      make_cleanup (set_thread_refcount, &ta_cleanup);
+      std::sort (thr_list_cpy.begin (), thr_list_cpy.end (), tp_array_compar);
 
-      for (k = 0; k != i; k++)
-	if (thread_alive (tp_array[k]))
+      for (thread_info *thr : thr_list_cpy)
+	if (thread_alive (thr))
 	  {
-	    switch_to_thread (tp_array[k]->ptid);
+	    switch_to_thread (thr->ptid);
 	    printf_filtered (_("\nThread %s (%s):\n"),
-			     print_thread_id (tp_array[k]),
+			     print_thread_id (thr),
 			     target_pid_to_str (inferior_ptid));
 	    execute_command (cmd, from_tty);
 
-- 
2.5.5


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]