1 /* Thread iterators and ranges for GDB, the GNU debugger. 2 Copyright (C) 2018-2019 Free Software Foundation, Inc. 3 4 This file is part of GDB. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 19 #ifndef THREAD_ITER_H 20 #define THREAD_ITER_H 21 22 #include "common/filtered-iterator.h" 23 #include "common/next-iterator.h" 24 #include "common/safe-iterator.h" 25 26 /* A forward iterator that iterates over a given inferior's 27 threads. */ 28 29 using inf_threads_iterator = next_iterator<thread_info>; 30 31 /* A forward iterator that iterates over all threads of all 32 inferiors. */ 33 34 class all_threads_iterator 35 { 36 public: 37 typedef all_threads_iterator self_type; 38 typedef struct thread_info *value_type; 39 typedef struct thread_info *&reference; 40 typedef struct thread_info **pointer; 41 typedef std::forward_iterator_tag iterator_category; 42 typedef int difference_type; 43 44 /* Tag type. */ 45 struct begin_t {}; 46 47 /* Create an iterator that points to the first thread of the first 48 inferior. */ 49 explicit all_threads_iterator (begin_t); 50 51 /* Create a one-past-end iterator. */ 52 all_threads_iterator () 53 : m_thr (nullptr) 54 {} 55 56 thread_info *operator* () const { return m_thr; } 57 58 all_threads_iterator &operator++ () 59 { 60 advance (); 61 return *this; 62 } 63 64 bool operator== (const all_threads_iterator &other) const 65 { return m_thr == other.m_thr; } 66 67 bool operator!= (const all_threads_iterator &other) const 68 { return m_thr != other.m_thr; } 69 70 private: 71 /* Advance to the next thread. */ 72 void advance (); 73 74 private: 75 /* The current inferior and thread. M_THR is NULL if we reached the 76 end of the threads list of the last inferior. */ 77 inferior *m_inf; 78 thread_info *m_thr; 79 }; 80 81 /* Iterate over all threads that match a given PTID. */ 82 83 class all_matching_threads_iterator 84 { 85 public: 86 typedef all_matching_threads_iterator self_type; 87 typedef struct thread_info *value_type; 88 typedef struct thread_info *&reference; 89 typedef struct thread_info **pointer; 90 typedef std::forward_iterator_tag iterator_category; 91 typedef int difference_type; 92 93 /* Creates an iterator that iterates over all threads that match 94 FILTER_PTID. */ 95 explicit all_matching_threads_iterator (ptid_t filter_ptid); 96 97 /* Create a one-past-end iterator. */ 98 all_matching_threads_iterator () 99 : m_inf (nullptr), 100 m_thr (nullptr), 101 m_filter_ptid (minus_one_ptid) 102 {} 103 104 thread_info *operator* () const { return m_thr; } 105 106 all_matching_threads_iterator &operator++ () 107 { 108 advance (); 109 return *this; 110 } 111 112 bool operator== (const all_matching_threads_iterator &other) const 113 { return m_thr == other.m_thr; } 114 115 bool operator!= (const all_matching_threads_iterator &other) const 116 { return m_thr != other.m_thr; } 117 118 private: 119 /* Advance to next thread, skipping filtered threads. */ 120 void advance (); 121 122 /* True if M_INF matches the process identified by 123 M_FILTER_PTID. */ 124 bool m_inf_matches (); 125 126 private: 127 /* The current inferior. */ 128 inferior *m_inf; 129 130 /* The current thread. */ 131 thread_info *m_thr; 132 133 /* The filter. */ 134 ptid_t m_filter_ptid; 135 }; 136 137 /* Filter for filtered_iterator. Filters out exited threads. */ 138 139 struct non_exited_thread_filter 140 { 141 bool operator() (struct thread_info *thr) const 142 { 143 return thr->state != THREAD_EXITED; 144 } 145 }; 146 147 /* Iterate over all non-exited threads that match a given PTID. */ 148 149 using all_non_exited_threads_iterator 150 = filtered_iterator<all_matching_threads_iterator, non_exited_thread_filter>; 151 152 /* Iterate over all non-exited threads of an inferior. */ 153 154 using inf_non_exited_threads_iterator 155 = filtered_iterator<inf_threads_iterator, non_exited_thread_filter>; 156 157 /* Iterate over all threads of all inferiors, safely. */ 158 159 using all_threads_safe_iterator 160 = basic_safe_iterator<all_threads_iterator>; 161 162 /* Iterate over all threads of an inferior, safely. */ 163 164 using safe_inf_threads_iterator 165 = basic_safe_iterator<inf_threads_iterator>; 166 167 /* A range adapter that makes it possible to iterate over all threads 168 of an inferior with range-for. */ 169 170 using inf_threads_range 171 = next_adapter<thread_info, inf_threads_iterator>; 172 173 /* A range adapter that makes it possible to iterate over all 174 non-exited threads of an inferior with range-for. */ 175 176 using inf_non_exited_threads_range 177 = next_adapter<thread_info, inf_non_exited_threads_iterator>; 178 179 /* A range adapter that makes it possible to iterate over all threads 180 of an inferior with range-for, safely. */ 181 182 using safe_inf_threads_range 183 = next_adapter<thread_info, safe_inf_threads_iterator>; 184 185 /* A range adapter that makes it possible to iterate over all threads 186 of all inferiors with range-for. */ 187 188 struct all_threads_range 189 { 190 all_threads_iterator begin () const 191 { return all_threads_iterator (all_threads_iterator::begin_t {}); } 192 all_threads_iterator end () const 193 { return all_threads_iterator (); } 194 }; 195 196 /* A range adapter that makes it possible to iterate over all threads 197 with range-for "safely". I.e., it is safe to delete the 198 currently-iterated thread. */ 199 200 struct all_threads_safe_range 201 { 202 all_threads_safe_iterator begin () const 203 { return all_threads_safe_iterator (all_threads_iterator::begin_t {}); } 204 all_threads_safe_iterator end () const 205 { return all_threads_safe_iterator (); } 206 }; 207 208 /* A range adapter that makes it possible to iterate over all threads 209 that match a PTID filter with range-for. */ 210 211 struct all_matching_threads_range 212 { 213 public: 214 explicit all_matching_threads_range (ptid_t filter_ptid) 215 : m_filter_ptid (filter_ptid) 216 {} 217 all_matching_threads_range () 218 : m_filter_ptid (minus_one_ptid) 219 {} 220 221 all_matching_threads_iterator begin () const 222 { return all_matching_threads_iterator (m_filter_ptid); } 223 all_matching_threads_iterator end () const 224 { return all_matching_threads_iterator (); } 225 226 private: 227 /* The filter. */ 228 ptid_t m_filter_ptid; 229 }; 230 231 /* A range adapter that makes it possible to iterate over all 232 non-exited threads of all inferiors, with range-for. 233 Threads/inferiors that do not match FILTER_PTID are filtered 234 out. */ 235 236 class all_non_exited_threads_range 237 { 238 public: 239 explicit all_non_exited_threads_range (ptid_t filter_ptid) 240 : m_filter_ptid (filter_ptid) 241 {} 242 243 all_non_exited_threads_range () 244 : m_filter_ptid (minus_one_ptid) 245 {} 246 247 all_non_exited_threads_iterator begin () const 248 { return all_non_exited_threads_iterator (m_filter_ptid); } 249 all_non_exited_threads_iterator end () const 250 { return all_non_exited_threads_iterator (); } 251 252 private: 253 ptid_t m_filter_ptid; 254 }; 255 256 #endif /* THREAD_ITER_H */ 257