17f2ac410Schristos /* Thread iterators and ranges for GDB, the GNU debugger. 2*6881a400Schristos Copyright (C) 2018-2023 Free Software Foundation, Inc. 37f2ac410Schristos 47f2ac410Schristos This file is part of GDB. 57f2ac410Schristos 67f2ac410Schristos This program is free software; you can redistribute it and/or modify 77f2ac410Schristos it under the terms of the GNU General Public License as published by 87f2ac410Schristos the Free Software Foundation; either version 3 of the License, or 97f2ac410Schristos (at your option) any later version. 107f2ac410Schristos 117f2ac410Schristos This program is distributed in the hope that it will be useful, 127f2ac410Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 137f2ac410Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 147f2ac410Schristos GNU General Public License for more details. 157f2ac410Schristos 167f2ac410Schristos You should have received a copy of the GNU General Public License 177f2ac410Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 187f2ac410Schristos 197f2ac410Schristos #ifndef THREAD_ITER_H 207f2ac410Schristos #define THREAD_ITER_H 217f2ac410Schristos 227d62b00eSchristos #include "gdbsupport/filtered-iterator.h" 23*6881a400Schristos #include "gdbsupport/iterator-range.h" 247d62b00eSchristos #include "gdbsupport/next-iterator.h" 25*6881a400Schristos #include "gdbsupport/reference-to-pointer-iterator.h" 267d62b00eSchristos #include "gdbsupport/safe-iterator.h" 277f2ac410Schristos 287f2ac410Schristos /* A forward iterator that iterates over a given inferior's 297f2ac410Schristos threads. */ 307f2ac410Schristos 31*6881a400Schristos using inf_threads_iterator 32*6881a400Schristos = reference_to_pointer_iterator<intrusive_list<thread_info>::iterator>; 337f2ac410Schristos 347f2ac410Schristos /* A forward iterator that iterates over all threads of all 357f2ac410Schristos inferiors. */ 367f2ac410Schristos 377f2ac410Schristos class all_threads_iterator 387f2ac410Schristos { 397f2ac410Schristos public: 407f2ac410Schristos typedef all_threads_iterator self_type; 417f2ac410Schristos typedef struct thread_info *value_type; 427f2ac410Schristos typedef struct thread_info *&reference; 437f2ac410Schristos typedef struct thread_info **pointer; 447f2ac410Schristos typedef std::forward_iterator_tag iterator_category; 457f2ac410Schristos typedef int difference_type; 467f2ac410Schristos 477f2ac410Schristos /* Tag type. */ 487f2ac410Schristos struct begin_t {}; 497f2ac410Schristos 507f2ac410Schristos /* Create an iterator that points to the first thread of the first 517f2ac410Schristos inferior. */ 527f2ac410Schristos explicit all_threads_iterator (begin_t); 537f2ac410Schristos 547f2ac410Schristos /* Create a one-past-end iterator. */ 557f2ac410Schristos all_threads_iterator () 567f2ac410Schristos : m_thr (nullptr) 577f2ac410Schristos {} 587f2ac410Schristos 597f2ac410Schristos thread_info *operator* () const { return m_thr; } 607f2ac410Schristos 617f2ac410Schristos all_threads_iterator &operator++ () 627f2ac410Schristos { 637f2ac410Schristos advance (); 647f2ac410Schristos return *this; 657f2ac410Schristos } 667f2ac410Schristos 677f2ac410Schristos bool operator== (const all_threads_iterator &other) const 687f2ac410Schristos { return m_thr == other.m_thr; } 697f2ac410Schristos 707f2ac410Schristos bool operator!= (const all_threads_iterator &other) const 717f2ac410Schristos { return m_thr != other.m_thr; } 727f2ac410Schristos 737f2ac410Schristos private: 747f2ac410Schristos /* Advance to the next thread. */ 757f2ac410Schristos void advance (); 767f2ac410Schristos 777f2ac410Schristos private: 787f2ac410Schristos /* The current inferior and thread. M_THR is NULL if we reached the 797f2ac410Schristos end of the threads list of the last inferior. */ 807f2ac410Schristos inferior *m_inf; 817f2ac410Schristos thread_info *m_thr; 827f2ac410Schristos }; 837f2ac410Schristos 847f2ac410Schristos /* Iterate over all threads that match a given PTID. */ 857f2ac410Schristos 867f2ac410Schristos class all_matching_threads_iterator 877f2ac410Schristos { 887f2ac410Schristos public: 897f2ac410Schristos typedef all_matching_threads_iterator self_type; 907f2ac410Schristos typedef struct thread_info *value_type; 917f2ac410Schristos typedef struct thread_info *&reference; 927f2ac410Schristos typedef struct thread_info **pointer; 937f2ac410Schristos typedef std::forward_iterator_tag iterator_category; 947f2ac410Schristos typedef int difference_type; 957f2ac410Schristos 967f2ac410Schristos /* Creates an iterator that iterates over all threads that match 977f2ac410Schristos FILTER_PTID. */ 987d62b00eSchristos all_matching_threads_iterator (process_stratum_target *filter_target, 997d62b00eSchristos ptid_t filter_ptid); 1007f2ac410Schristos 1017f2ac410Schristos /* Create a one-past-end iterator. */ 102*6881a400Schristos all_matching_threads_iterator () = default; 1037f2ac410Schristos 1047f2ac410Schristos thread_info *operator* () const { return m_thr; } 1057f2ac410Schristos 1067f2ac410Schristos all_matching_threads_iterator &operator++ () 1077f2ac410Schristos { 1087f2ac410Schristos advance (); 1097f2ac410Schristos return *this; 1107f2ac410Schristos } 1117f2ac410Schristos 1127f2ac410Schristos bool operator== (const all_matching_threads_iterator &other) const 1137f2ac410Schristos { return m_thr == other.m_thr; } 1147f2ac410Schristos 1157f2ac410Schristos bool operator!= (const all_matching_threads_iterator &other) const 1167f2ac410Schristos { return m_thr != other.m_thr; } 1177f2ac410Schristos 1187f2ac410Schristos private: 1197f2ac410Schristos /* Advance to next thread, skipping filtered threads. */ 1207f2ac410Schristos void advance (); 1217f2ac410Schristos 122*6881a400Schristos /* True if M_INF has the process target M_FILTER_TARGET. */ 1237f2ac410Schristos bool m_inf_matches (); 1247f2ac410Schristos 1257f2ac410Schristos private: 126*6881a400Schristos enum class mode 127*6881a400Schristos { 128*6881a400Schristos /* All threads, possibly filtered down to a single target. */ 129*6881a400Schristos ALL_THREADS, 130*6881a400Schristos 131*6881a400Schristos /* All threads of the given inferior. */ 132*6881a400Schristos ALL_THREADS_OF_INFERIOR, 133*6881a400Schristos 134*6881a400Schristos /* A specific thread. */ 135*6881a400Schristos SINGLE_THREAD, 136*6881a400Schristos } m_mode; 137*6881a400Schristos 1387f2ac410Schristos /* The current inferior. */ 139*6881a400Schristos inferior *m_inf = nullptr; 1407f2ac410Schristos 1417f2ac410Schristos /* The current thread. */ 142*6881a400Schristos thread_info *m_thr = nullptr; 1437f2ac410Schristos 144*6881a400Schristos /* The target we filter on (may be nullptr). */ 1457d62b00eSchristos process_stratum_target *m_filter_target; 1467f2ac410Schristos }; 1477f2ac410Schristos 1487f2ac410Schristos /* Filter for filtered_iterator. Filters out exited threads. */ 1497f2ac410Schristos 1507f2ac410Schristos struct non_exited_thread_filter 1517f2ac410Schristos { 1527f2ac410Schristos bool operator() (struct thread_info *thr) const 1537f2ac410Schristos { 1547f2ac410Schristos return thr->state != THREAD_EXITED; 1557f2ac410Schristos } 1567f2ac410Schristos }; 1577f2ac410Schristos 1587f2ac410Schristos /* Iterate over all non-exited threads that match a given PTID. */ 1597f2ac410Schristos 1607f2ac410Schristos using all_non_exited_threads_iterator 1617f2ac410Schristos = filtered_iterator<all_matching_threads_iterator, non_exited_thread_filter>; 1627f2ac410Schristos 1637f2ac410Schristos /* Iterate over all non-exited threads of an inferior. */ 1647f2ac410Schristos 1657f2ac410Schristos using inf_non_exited_threads_iterator 1667f2ac410Schristos = filtered_iterator<inf_threads_iterator, non_exited_thread_filter>; 1677f2ac410Schristos 1687f2ac410Schristos /* Iterate over all threads of all inferiors, safely. */ 1697f2ac410Schristos 1707f2ac410Schristos using all_threads_safe_iterator 1717f2ac410Schristos = basic_safe_iterator<all_threads_iterator>; 1727f2ac410Schristos 1737f2ac410Schristos /* Iterate over all threads of an inferior, safely. */ 1747f2ac410Schristos 1757f2ac410Schristos using safe_inf_threads_iterator 1767f2ac410Schristos = basic_safe_iterator<inf_threads_iterator>; 1777f2ac410Schristos 1787f2ac410Schristos /* A range adapter that makes it possible to iterate over all threads 1797f2ac410Schristos of an inferior with range-for. */ 1807f2ac410Schristos 181*6881a400Schristos using inf_threads_range = iterator_range<inf_threads_iterator>; 1827f2ac410Schristos 1837f2ac410Schristos /* A range adapter that makes it possible to iterate over all 1847f2ac410Schristos non-exited threads of an inferior with range-for. */ 1857f2ac410Schristos 1867f2ac410Schristos using inf_non_exited_threads_range 187*6881a400Schristos = iterator_range<inf_non_exited_threads_iterator>; 1887f2ac410Schristos 1897f2ac410Schristos /* A range adapter that makes it possible to iterate over all threads 1907f2ac410Schristos of an inferior with range-for, safely. */ 1917f2ac410Schristos 192*6881a400Schristos using safe_inf_threads_range = iterator_range<safe_inf_threads_iterator>; 1937f2ac410Schristos 1947f2ac410Schristos /* A range adapter that makes it possible to iterate over all threads 1957f2ac410Schristos with range-for "safely". I.e., it is safe to delete the 1967f2ac410Schristos currently-iterated thread. */ 1977f2ac410Schristos 198*6881a400Schristos using all_threads_safe_range = iterator_range<all_threads_safe_iterator>; 1997f2ac410Schristos 2007f2ac410Schristos /* A range adapter that makes it possible to iterate over all threads 2017f2ac410Schristos that match a PTID filter with range-for. */ 2027f2ac410Schristos 2037f2ac410Schristos struct all_matching_threads_range 2047f2ac410Schristos { 2057f2ac410Schristos public: 2067d62b00eSchristos all_matching_threads_range (process_stratum_target *filter_target, 2077d62b00eSchristos ptid_t filter_ptid) 2087d62b00eSchristos : m_filter_target (filter_target), m_filter_ptid (filter_ptid) 2097f2ac410Schristos {} 2107f2ac410Schristos all_matching_threads_range () 2117d62b00eSchristos : m_filter_target (nullptr), m_filter_ptid (minus_one_ptid) 2127f2ac410Schristos {} 2137f2ac410Schristos 2147f2ac410Schristos all_matching_threads_iterator begin () const 2157d62b00eSchristos { return all_matching_threads_iterator (m_filter_target, m_filter_ptid); } 2167f2ac410Schristos all_matching_threads_iterator end () const 2177f2ac410Schristos { return all_matching_threads_iterator (); } 2187f2ac410Schristos 2197f2ac410Schristos private: 2207f2ac410Schristos /* The filter. */ 2217d62b00eSchristos process_stratum_target *m_filter_target; 2227f2ac410Schristos ptid_t m_filter_ptid; 2237f2ac410Schristos }; 2247f2ac410Schristos 2257f2ac410Schristos /* A range adapter that makes it possible to iterate over all 2267f2ac410Schristos non-exited threads of all inferiors, with range-for. 2277f2ac410Schristos Threads/inferiors that do not match FILTER_PTID are filtered 2287f2ac410Schristos out. */ 2297f2ac410Schristos 2307f2ac410Schristos class all_non_exited_threads_range 2317f2ac410Schristos { 2327f2ac410Schristos public: 2337d62b00eSchristos all_non_exited_threads_range (process_stratum_target *filter_target, 2347d62b00eSchristos ptid_t filter_ptid) 2357d62b00eSchristos : m_filter_target (filter_target), m_filter_ptid (filter_ptid) 2367f2ac410Schristos {} 2377f2ac410Schristos 2387f2ac410Schristos all_non_exited_threads_range () 2397d62b00eSchristos : m_filter_target (nullptr), m_filter_ptid (minus_one_ptid) 2407f2ac410Schristos {} 2417f2ac410Schristos 2427f2ac410Schristos all_non_exited_threads_iterator begin () const 2437d62b00eSchristos { return all_non_exited_threads_iterator (m_filter_target, m_filter_ptid); } 2447f2ac410Schristos all_non_exited_threads_iterator end () const 2457f2ac410Schristos { return all_non_exited_threads_iterator (); } 2467f2ac410Schristos 2477f2ac410Schristos private: 2487d62b00eSchristos process_stratum_target *m_filter_target; 2497f2ac410Schristos ptid_t m_filter_ptid; 2507f2ac410Schristos }; 2517f2ac410Schristos 2527f2ac410Schristos #endif /* THREAD_ITER_H */ 253