xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/thread-iter.h (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
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