1 /* Inferior iterators and ranges for GDB, the GNU debugger. 2 3 Copyright (C) 2018-2020 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 #ifndef INFERIOR_ITER_H 21 #define INFERIOR_ITER_H 22 23 #include "gdbsupport/filtered-iterator.h" 24 #include "gdbsupport/safe-iterator.h" 25 26 /* A forward iterator that iterates over all inferiors. */ 27 28 class all_inferiors_iterator 29 { 30 public: 31 typedef all_inferiors_iterator self_type; 32 typedef struct inferior *value_type; 33 typedef struct inferior *&reference; 34 typedef struct inferior **pointer; 35 typedef std::forward_iterator_tag iterator_category; 36 typedef int difference_type; 37 38 /* Create an iterator pointing at HEAD. */ 39 all_inferiors_iterator (process_stratum_target *proc_target, inferior *head) 40 : m_proc_target (proc_target) 41 { 42 /* Advance M_INF to the first inferior's position. */ 43 for (m_inf = head; m_inf != NULL; m_inf = m_inf->next) 44 if (m_inf_matches ()) 45 return; 46 } 47 48 /* Create a one-past-end iterator. */ 49 all_inferiors_iterator () 50 : m_proc_target (nullptr), m_inf (nullptr) 51 {} 52 53 all_inferiors_iterator &operator++ () 54 { 55 advance (); 56 return *this; 57 } 58 59 inferior *operator* () const 60 { return m_inf; } 61 62 bool operator!= (const all_inferiors_iterator &other) const 63 { return m_inf != other.m_inf; } 64 65 private: 66 /* Advance to next inferior, skipping filtered inferiors. */ 67 void advance () 68 { 69 /* The loop below is written in the natural way as-if we'd always 70 start at the beginning of the inferior list. This 71 fast-forwards the algorithm to the actual current position. */ 72 goto start; 73 74 while (m_inf != NULL) 75 { 76 if (m_inf_matches ()) 77 return; 78 start: 79 m_inf = m_inf->next; 80 } 81 } 82 83 bool m_inf_matches () 84 { 85 return (m_proc_target == nullptr 86 || m_proc_target == m_inf->process_target ()); 87 } 88 89 process_stratum_target *m_proc_target; 90 inferior *m_inf; 91 }; 92 93 /* Filter for filtered_iterator. Filters out exited inferiors. */ 94 95 struct exited_inferior_filter 96 { 97 bool operator() (inferior *inf) 98 { 99 return inf->pid != 0; 100 } 101 }; 102 103 /* Iterate over all non-exited inferiors. */ 104 105 using all_non_exited_inferiors_iterator 106 = filtered_iterator<all_inferiors_iterator, exited_inferior_filter>; 107 108 /* A range adapter that makes it possible to iterate over all 109 inferiors with range-for. */ 110 struct all_inferiors_range 111 { 112 all_inferiors_range (process_stratum_target *proc_target = nullptr) 113 : m_filter_target (proc_target) 114 {} 115 116 all_inferiors_iterator begin () const 117 { return all_inferiors_iterator (m_filter_target, inferior_list); } 118 all_inferiors_iterator end () const 119 { return all_inferiors_iterator (); } 120 121 private: 122 process_stratum_target *m_filter_target; 123 }; 124 125 /* Iterate over all inferiors, safely. */ 126 127 using all_inferiors_safe_iterator 128 = basic_safe_iterator<all_inferiors_iterator>; 129 130 /* A range adapter that makes it possible to iterate over all 131 inferiors with range-for "safely". I.e., it is safe to delete the 132 currently-iterated inferior. */ 133 134 struct all_inferiors_safe_range 135 { 136 explicit all_inferiors_safe_range (process_stratum_target *filter_target) 137 : m_filter_target (filter_target) 138 {} 139 140 all_inferiors_safe_range () 141 : m_filter_target (nullptr) 142 {} 143 144 all_inferiors_safe_iterator begin () const 145 { 146 return (all_inferiors_safe_iterator 147 (all_inferiors_iterator (m_filter_target, inferior_list))); 148 } 149 150 all_inferiors_safe_iterator end () const 151 { return all_inferiors_safe_iterator (); } 152 153 private: 154 /* The filter. */ 155 process_stratum_target *m_filter_target; 156 }; 157 158 /* A range adapter that makes it possible to iterate over all 159 non-exited inferiors with range-for. */ 160 161 struct all_non_exited_inferiors_range 162 { 163 explicit all_non_exited_inferiors_range (process_stratum_target *filter_target) 164 : m_filter_target (filter_target) 165 {} 166 167 all_non_exited_inferiors_range () 168 : m_filter_target (nullptr) 169 {} 170 171 all_non_exited_inferiors_iterator begin () const 172 { return all_non_exited_inferiors_iterator (m_filter_target, inferior_list); } 173 all_non_exited_inferiors_iterator end () const 174 { return all_non_exited_inferiors_iterator (); } 175 176 private: 177 /* The filter. */ 178 process_stratum_target *m_filter_target; 179 }; 180 181 #endif /* !defined (INFERIOR_ITER_H) */ 182