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:
parent
2a00d7ce26
commit
c6609450b3
|
@ -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>
|
||||
|
||||
* infrun.c (follow_fork_inferior): Also switch the current
|
||||
|
|
131
gdb/thread.c
131
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++;
|
||||
thr_list_cpy.push_back (tp);
|
||||
}
|
||||
/* 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);
|
||||
gdb_assert (thr_list_cpy.size () == tc);
|
||||
}
|
||||
|
||||
ta_cleanup.tp_array = tp_array;
|
||||
ta_cleanup.count = i;
|
||||
make_cleanup (set_thread_refcount, &ta_cleanup);
|
||||
/* Increment the refcounts, and restore them back on scope
|
||||
exit. */
|
||||
scoped_inc_dec_ref inc_dec_ref (thr_list_cpy);
|
||||
|
||||
for (k = 0; k != i; k++)
|
||||
if (thread_alive (tp_array[k]))
|
||||
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 (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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue