C++fy thread_apply_all_command

This eliminates a couple cleanups.

gdb/ChangeLog:
2017-04-13  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.
This commit is contained in:
Pedro Alves 2017-04-13 16:15:34 +01:00
parent 2a00d7ce26
commit c6609450b3
2 changed files with 88 additions and 67 deletions

View File

@ -1,3 +1,15 @@
2017-04-13 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.
2017-04-13 Pedro Alves <palves@redhat.com> 2017-04-13 Pedro Alves <palves@redhat.com>
* infrun.c (follow_fork_inferior): Also switch the current * infrun.c (follow_fork_inferior): Also switch the current

View File

@ -44,6 +44,7 @@
#include "cli/cli-utils.h" #include "cli/cli-utils.h"
#include "thread-fsm.h" #include "thread-fsm.h"
#include "tid-parse.h" #include "tid-parse.h"
#include <algorithm>
/* Definition of struct thread_info exported to gdbthread.h. */ /* 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 thread_apply_command (char *, int);
static void restore_current_thread (ptid_t); 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 public:
reference count. */ explicit scoped_inc_dec_ref (const std::vector<thread_info *> &thrds)
struct thread_info **tp_array; : m_thrds (thrds)
{
for (thread_info *thr : m_thrds)
thr->incref ();
}
/* Thread count in the array. */ ~scoped_inc_dec_ref ()
int count; {
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 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 int
valid_global_thread_id (int global_id) valid_global_thread_id (int global_id)
{ {
@ -1605,19 +1631,6 @@ restore_current_thread_cleanup_dtor (void *arg)
xfree (old); 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 * struct cleanup *
make_cleanup_restore_current_thread (void) make_cleanup_restore_current_thread (void)
{ {
@ -1693,30 +1706,30 @@ print_thread_id (struct thread_info *thr)
return s; return s;
} }
/* If non-zero tp_array_compar should sort in ascending order, otherwise in /* If true, tp_array_compar should sort in ascending order, otherwise
descending order. */ 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 /* Sort an array for struct thread_info pointers by thread ID (first
by inferior number, and then by per-inferior thread number). The by inferior number, and then by per-inferior thread number). The
order is determined by TP_ARRAY_COMPAR_ASCENDING. */ order is determined by TP_ARRAY_COMPAR_ASCENDING. */
static int static bool
tp_array_compar (const void *ap_voidp, const void *bp_voidp) 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) if (a->inf->num != b->inf->num)
{ {
return (((a->inf->num > b->inf->num) - (a->inf->num < b->inf->num)) if (tp_array_compar_ascending)
* (tp_array_compar_ascending ? +1 : -1)); return a->inf->num < b->inf->num;
else
return a->inf->num > b->inf->num;
} }
return (((a->per_inf_num > b->per_inf_num) if (tp_array_compar_ascending)
- (a->per_inf_num < b->per_inf_num)) return (a->per_inf_num < b->per_inf_num);
* (tp_array_compar_ascending ? +1 : -1)); else
return (a->per_inf_num > b->per_inf_num);
} }
/* Apply a GDB command to a list of threads. List syntax is a whitespace /* 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; struct cleanup *old_chain;
char *saved_cmd; char *saved_cmd;
int tc;
struct thread_array_cleanup ta_cleanup;
tp_array_compar_ascending = 0; tp_array_compar_ascending = false;
if (cmd != NULL if (cmd != NULL
&& check_for_argument (&cmd, "-ascending", strlen ("-ascending"))) && check_for_argument (&cmd, "-ascending", strlen ("-ascending")))
{ {
cmd = skip_spaces (cmd); cmd = skip_spaces (cmd);
tp_array_compar_ascending = 1; tp_array_compar_ascending = true;
} }
if (cmd == NULL || *cmd == '\000') if (cmd == NULL || *cmd == '\000')
@ -1755,42 +1766,40 @@ thread_apply_all_command (char *cmd, int from_tty)
saved_cmd = xstrdup (cmd); saved_cmd = xstrdup (cmd);
make_cleanup (xfree, saved_cmd); make_cleanup (xfree, saved_cmd);
/* Note this includes exited threads. */ int tc = live_threads_count ();
tc = thread_count ();
if (tc != 0) if (tc != 0)
{ {
struct thread_info **tp_array; /* Save a copy of the thread list and increment each thread's
struct thread_info *tp; refcount while executing the command in the context of each
int i = 0, k; 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. */ thread_info *tp;
tp_array = XNEWVEC (struct thread_info *, tc);
make_cleanup (xfree, tp_array);
ALL_NON_EXITED_THREADS (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);
if (i != 0)
qsort (tp_array, i, sizeof (*tp_array), tp_array_compar);
ta_cleanup.tp_array = tp_array;
ta_cleanup.count = i;
make_cleanup (set_thread_refcount, &ta_cleanup);
for (k = 0; k != i; k++)
if (thread_alive (tp_array[k]))
{ {
switch_to_thread (tp_array[k]->ptid); thr_list_cpy.push_back (tp);
}
gdb_assert (thr_list_cpy.size () == tc);
}
/* Increment the refcounts, and restore them back on scope
exit. */
scoped_inc_dec_ref inc_dec_ref (thr_list_cpy);
std::sort (thr_list_cpy.begin (), thr_list_cpy.end (), tp_array_compar);
for (thread_info *thr : thr_list_cpy)
if (thread_alive (thr))
{
switch_to_thread (thr->ptid);
printf_filtered (_("\nThread %s (%s):\n"), printf_filtered (_("\nThread %s (%s):\n"),
print_thread_id (tp_array[k]), print_thread_id (thr),
target_pid_to_str (inferior_ptid)); target_pid_to_str (inferior_ptid));
execute_command (cmd, from_tty); execute_command (cmd, from_tty);