1 //===-- BreakpointList.cpp --------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Breakpoint/BreakpointList.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Target/Target.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 BreakpointList::BreakpointList (bool is_internal) :
22     m_mutex (Mutex::eMutexTypeRecursive),
23     m_breakpoints(),
24     m_next_break_id (0),
25     m_is_internal (is_internal)
26 {
27 }
28 
29 BreakpointList::~BreakpointList()
30 {
31 }
32 
33 
34 break_id_t
35 BreakpointList::Add (BreakpointSP &bp_sp, bool notify)
36 {
37     Mutex::Locker locker(m_mutex);
38     // Internal breakpoint IDs are negative, normal ones are positive
39     bp_sp->SetID (m_is_internal ? --m_next_break_id : ++m_next_break_id);
40 
41     m_breakpoints.push_back(bp_sp);
42     if (notify)
43     {
44         if (bp_sp->GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
45             bp_sp->GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged,
46                                                new Breakpoint::BreakpointEventData (eBreakpointEventTypeAdded, bp_sp));
47     }
48     return bp_sp->GetID();
49 }
50 
51 bool
52 BreakpointList::Remove (break_id_t break_id, bool notify)
53 {
54     Mutex::Locker locker(m_mutex);
55     bp_collection::iterator pos = GetBreakpointIDIterator(break_id);    // Predicate
56     if (pos != m_breakpoints.end())
57     {
58         BreakpointSP bp_sp (*pos);
59         m_breakpoints.erase(pos);
60         if (notify)
61         {
62             if (bp_sp->GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
63                 bp_sp->GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged,
64                                                    new Breakpoint::BreakpointEventData (eBreakpointEventTypeRemoved, bp_sp));
65         }
66         return true;
67     }
68     return false;
69 }
70 
71 void
72 BreakpointList::SetEnabledAll (bool enabled)
73 {
74     Mutex::Locker locker(m_mutex);
75     bp_collection::iterator pos, end = m_breakpoints.end();
76     for (pos = m_breakpoints.begin(); pos != end; ++pos)
77         (*pos)->SetEnabled (enabled);
78 }
79 
80 
81 void
82 BreakpointList::RemoveAll (bool notify)
83 {
84     Mutex::Locker locker(m_mutex);
85     ClearAllBreakpointSites ();
86 
87     if (notify)
88     {
89         bp_collection::iterator pos, end = m_breakpoints.end();
90         for (pos = m_breakpoints.begin(); pos != end; ++pos)
91             if ((*pos)->GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
92                 (*pos)->GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged,
93                                                     new Breakpoint::BreakpointEventData (eBreakpointEventTypeRemoved, *pos));
94     }
95     m_breakpoints.erase (m_breakpoints.begin(), m_breakpoints.end());
96 }
97 
98 class BreakpointIDMatches
99 {
100 public:
101     BreakpointIDMatches (break_id_t break_id) :
102         m_break_id(break_id)
103     {
104     }
105 
106     bool operator() (const BreakpointSP &bp) const
107     {
108         return m_break_id == bp->GetID();
109     }
110 
111 private:
112    const break_id_t m_break_id;
113 };
114 
115 BreakpointList::bp_collection::iterator
116 BreakpointList::GetBreakpointIDIterator (break_id_t break_id)
117 {
118     return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range
119                         BreakpointIDMatches(break_id));             // Predicate
120 }
121 
122 BreakpointList::bp_collection::const_iterator
123 BreakpointList::GetBreakpointIDConstIterator (break_id_t break_id) const
124 {
125     return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range
126                         BreakpointIDMatches(break_id));             // Predicate
127 }
128 
129 BreakpointSP
130 BreakpointList::FindBreakpointByID (break_id_t break_id)
131 {
132     Mutex::Locker locker(m_mutex);
133     BreakpointSP stop_sp;
134     bp_collection::iterator pos = GetBreakpointIDIterator(break_id);
135     if (pos != m_breakpoints.end())
136         stop_sp = *pos;
137 
138     return stop_sp;
139 }
140 
141 const BreakpointSP
142 BreakpointList::FindBreakpointByID (break_id_t break_id) const
143 {
144     Mutex::Locker locker(m_mutex);
145     BreakpointSP stop_sp;
146     bp_collection::const_iterator pos = GetBreakpointIDConstIterator(break_id);
147     if (pos != m_breakpoints.end())
148         stop_sp = *pos;
149 
150     return stop_sp;
151 }
152 
153 void
154 BreakpointList::Dump (Stream *s) const
155 {
156     Mutex::Locker locker(m_mutex);
157     s->Printf("%p: ", this);
158     s->Indent();
159     s->Printf("BreakpointList with %u Breakpoints:\n", (uint32_t)m_breakpoints.size());
160     s->IndentMore();
161     bp_collection::const_iterator pos;
162     bp_collection::const_iterator end = m_breakpoints.end();
163     for (pos = m_breakpoints.begin(); pos != end; ++pos)
164         (*pos)->Dump(s);
165     s->IndentLess();
166 }
167 
168 
169 BreakpointSP
170 BreakpointList::GetBreakpointAtIndex (uint32_t i)
171 {
172     Mutex::Locker locker(m_mutex);
173     BreakpointSP stop_sp;
174     bp_collection::iterator end = m_breakpoints.end();
175     bp_collection::iterator pos;
176     uint32_t curr_i = 0;
177     for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
178     {
179         if (curr_i == i)
180             stop_sp = *pos;
181     }
182     return stop_sp;
183 }
184 
185 const BreakpointSP
186 BreakpointList::GetBreakpointAtIndex (uint32_t i) const
187 {
188     Mutex::Locker locker(m_mutex);
189     BreakpointSP stop_sp;
190     bp_collection::const_iterator end = m_breakpoints.end();
191     bp_collection::const_iterator pos;
192     uint32_t curr_i = 0;
193     for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
194     {
195         if (curr_i == i)
196             stop_sp = *pos;
197     }
198     return stop_sp;
199 }
200 
201 void
202 BreakpointList::UpdateBreakpoints (ModuleList& module_list, bool added)
203 {
204     Mutex::Locker locker(m_mutex);
205     bp_collection::iterator end = m_breakpoints.end();
206     bp_collection::iterator pos;
207     for (pos = m_breakpoints.begin(); pos != end; ++pos)
208         (*pos)->ModulesChanged (module_list, added);
209 
210 }
211 
212 void
213 BreakpointList::ClearAllBreakpointSites ()
214 {
215     Mutex::Locker locker(m_mutex);
216     bp_collection::iterator end = m_breakpoints.end();
217     bp_collection::iterator pos;
218     for (pos = m_breakpoints.begin(); pos != end; ++pos)
219         (*pos)->ClearAllBreakpointSites ();
220 
221 }
222 
223 void
224 BreakpointList::GetListMutex (Mutex::Locker &locker)
225 {
226     return locker.Reset (m_mutex.GetMutex());
227 }
228