gdb: introduce intrusive_list, make thread_info use it
[binutils-gdb.git] / gdb / thread-iter.c
1 /* Thread iterators and ranges for GDB, the GNU debugger.
2
3 Copyright (C) 2018-2021 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "defs.h"
21 #include "gdbthread.h"
22 #include "inferior.h"
23
24 /* See thread-iter.h. */
25
26 all_threads_iterator::all_threads_iterator (begin_t)
27 {
28 /* Advance M_INF/M_THR to the first thread's position. */
29 for (m_inf = inferior_list; m_inf != NULL; m_inf = m_inf->next)
30 {
31 auto thr_iter = m_inf->thread_list.begin ();
32 if (thr_iter != m_inf->thread_list.end ())
33 {
34 m_thr = &*thr_iter;
35 return;
36 }
37 }
38 m_thr = nullptr;
39 }
40
41 /* See thread-iter.h. */
42
43 void
44 all_threads_iterator::advance ()
45 {
46 intrusive_list<thread_info>::iterator thr_iter (m_thr);
47
48 /* The loop below is written in the natural way as-if we'd always
49 start at the beginning of the inferior list. This fast forwards
50 the algorithm to the actual current position. */
51 goto start;
52
53 for (; m_inf != NULL; m_inf = m_inf->next)
54 {
55 thr_iter = m_inf->thread_list.begin ();
56 while (thr_iter != m_inf->thread_list.end ())
57 {
58 m_thr = &*thr_iter;
59 return;
60 start:
61 ++thr_iter;
62 }
63 }
64
65 m_thr = nullptr;
66 }
67
68 /* See thread-iter.h. */
69
70 bool
71 all_matching_threads_iterator::m_inf_matches ()
72 {
73 return ((m_filter_target == nullptr
74 || m_filter_target == m_inf->process_target ())
75 && (m_filter_ptid == minus_one_ptid
76 || m_filter_ptid.pid () == m_inf->pid));
77 }
78
79 /* See thread-iter.h. */
80
81 all_matching_threads_iterator::all_matching_threads_iterator
82 (process_stratum_target *filter_target, ptid_t filter_ptid)
83 : m_filter_target (filter_target),
84 m_filter_ptid (filter_ptid)
85 {
86 gdb_assert ((filter_target == nullptr && filter_ptid == minus_one_ptid)
87 || filter_target->stratum () == process_stratum);
88
89 for (m_inf = inferior_list; m_inf != NULL; m_inf = m_inf->next)
90 if (m_inf_matches ())
91 for (auto thr_iter = m_inf->thread_list.begin ();
92 thr_iter != m_inf->thread_list.end ();
93 ++thr_iter)
94 if (thr_iter->ptid.matches (m_filter_ptid))
95 {
96 m_thr = &*thr_iter;
97 return;
98 }
99
100 m_thr = nullptr;
101 }
102
103 /* See thread-iter.h. */
104
105 void
106 all_matching_threads_iterator::advance ()
107 {
108 intrusive_list<thread_info>::iterator thr_iter (m_thr);
109
110 /* The loop below is written in the natural way as-if we'd always
111 start at the beginning of the inferior list. This fast forwards
112 the algorithm to the actual current position. */
113 goto start;
114
115 for (; m_inf != NULL; m_inf = m_inf->next)
116 if (m_inf_matches ())
117 {
118 thr_iter = m_inf->thread_list.begin ();
119 while (thr_iter != m_inf->thread_list.end ())
120 {
121 if (thr_iter->ptid.matches (m_filter_ptid))
122 {
123 m_thr = &*thr_iter;
124 return;
125 }
126 start:
127 ++thr_iter;
128 }
129 }
130
131 m_thr = nullptr;
132 }