BreakpointList.cpp revision 309124
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
18using namespace lldb;
19using namespace lldb_private;
20
21BreakpointList::BreakpointList(bool is_internal)
22    : m_mutex(), m_breakpoints(), m_next_break_id(0), m_is_internal(is_internal)
23{
24}
25
26BreakpointList::~BreakpointList()
27{
28}
29
30
31break_id_t
32BreakpointList::Add (BreakpointSP &bp_sp, bool notify)
33{
34    std::lock_guard<std::recursive_mutex> guard(m_mutex);
35    // Internal breakpoint IDs are negative, normal ones are positive
36    bp_sp->SetID (m_is_internal ? --m_next_break_id : ++m_next_break_id);
37
38    m_breakpoints.push_back(bp_sp);
39    if (notify)
40    {
41        if (bp_sp->GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
42            bp_sp->GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged,
43                                               new Breakpoint::BreakpointEventData (eBreakpointEventTypeAdded, bp_sp));
44    }
45    return bp_sp->GetID();
46}
47
48bool
49BreakpointList::Remove (break_id_t break_id, bool notify)
50{
51    std::lock_guard<std::recursive_mutex> guard(m_mutex);
52    bp_collection::iterator pos = GetBreakpointIDIterator(break_id);    // Predicate
53    if (pos != m_breakpoints.end())
54    {
55        BreakpointSP bp_sp (*pos);
56        m_breakpoints.erase(pos);
57        if (notify)
58        {
59            if (bp_sp->GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
60                bp_sp->GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged,
61                                                   new Breakpoint::BreakpointEventData (eBreakpointEventTypeRemoved, bp_sp));
62        }
63        return true;
64    }
65    return false;
66}
67
68void
69BreakpointList::RemoveInvalidLocations (const ArchSpec &arch)
70{
71    std::lock_guard<std::recursive_mutex> guard(m_mutex);
72    for (const auto &bp_sp : m_breakpoints)
73        bp_sp->RemoveInvalidLocations(arch);
74}
75
76
77void
78BreakpointList::SetEnabledAll (bool enabled)
79{
80    std::lock_guard<std::recursive_mutex> guard(m_mutex);
81    for (const auto &bp_sp : m_breakpoints)
82        bp_sp->SetEnabled (enabled);
83}
84
85
86void
87BreakpointList::RemoveAll (bool notify)
88{
89    std::lock_guard<std::recursive_mutex> guard(m_mutex);
90    ClearAllBreakpointSites ();
91
92    if (notify)
93    {
94        bp_collection::iterator pos, end = m_breakpoints.end();
95        for (pos = m_breakpoints.begin(); pos != end; ++pos)
96        {
97            if ((*pos)->GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
98            {
99                (*pos)->GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged,
100                                                    new Breakpoint::BreakpointEventData (eBreakpointEventTypeRemoved,
101                                                                                         *pos));
102            }
103        }
104    }
105    m_breakpoints.erase (m_breakpoints.begin(), m_breakpoints.end());
106}
107
108class BreakpointIDMatches
109{
110public:
111    BreakpointIDMatches (break_id_t break_id) :
112        m_break_id(break_id)
113    {
114    }
115
116    bool operator() (const BreakpointSP &bp) const
117    {
118        return m_break_id == bp->GetID();
119    }
120
121private:
122   const break_id_t m_break_id;
123};
124
125BreakpointList::bp_collection::iterator
126BreakpointList::GetBreakpointIDIterator (break_id_t break_id)
127{
128    return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range
129                        BreakpointIDMatches(break_id));             // Predicate
130}
131
132BreakpointList::bp_collection::const_iterator
133BreakpointList::GetBreakpointIDConstIterator (break_id_t break_id) const
134{
135    return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range
136                        BreakpointIDMatches(break_id));             // Predicate
137}
138
139BreakpointSP
140BreakpointList::FindBreakpointByID (break_id_t break_id)
141{
142    std::lock_guard<std::recursive_mutex> guard(m_mutex);
143    BreakpointSP stop_sp;
144    bp_collection::iterator pos = GetBreakpointIDIterator(break_id);
145    if (pos != m_breakpoints.end())
146        stop_sp = *pos;
147
148    return stop_sp;
149}
150
151const BreakpointSP
152BreakpointList::FindBreakpointByID (break_id_t break_id) const
153{
154    std::lock_guard<std::recursive_mutex> guard(m_mutex);
155    BreakpointSP stop_sp;
156    bp_collection::const_iterator pos = GetBreakpointIDConstIterator(break_id);
157    if (pos != m_breakpoints.end())
158        stop_sp = *pos;
159
160    return stop_sp;
161}
162
163void
164BreakpointList::Dump (Stream *s) const
165{
166    std::lock_guard<std::recursive_mutex> guard(m_mutex);
167    s->Printf("%p: ", static_cast<const void*>(this));
168    s->Indent();
169    s->Printf("BreakpointList with %u Breakpoints:\n", (uint32_t)m_breakpoints.size());
170    s->IndentMore();
171    for (const auto &bp_sp : m_breakpoints)
172        bp_sp->Dump(s);
173    s->IndentLess();
174}
175
176
177BreakpointSP
178BreakpointList::GetBreakpointAtIndex (size_t i)
179{
180    std::lock_guard<std::recursive_mutex> guard(m_mutex);
181    BreakpointSP stop_sp;
182    bp_collection::iterator end = m_breakpoints.end();
183    bp_collection::iterator pos;
184    size_t curr_i = 0;
185    for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
186    {
187        if (curr_i == i)
188            stop_sp = *pos;
189    }
190    return stop_sp;
191}
192
193const BreakpointSP
194BreakpointList::GetBreakpointAtIndex (size_t i) const
195{
196    std::lock_guard<std::recursive_mutex> guard(m_mutex);
197    BreakpointSP stop_sp;
198    bp_collection::const_iterator end = m_breakpoints.end();
199    bp_collection::const_iterator pos;
200    size_t curr_i = 0;
201    for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
202    {
203        if (curr_i == i)
204            stop_sp = *pos;
205    }
206    return stop_sp;
207}
208
209void
210BreakpointList::UpdateBreakpoints (ModuleList& module_list, bool added, bool delete_locations)
211{
212    std::lock_guard<std::recursive_mutex> guard(m_mutex);
213    for (const auto &bp_sp : m_breakpoints)
214        bp_sp->ModulesChanged (module_list, added, delete_locations);
215
216}
217
218void
219BreakpointList::UpdateBreakpointsWhenModuleIsReplaced (ModuleSP old_module_sp, ModuleSP new_module_sp)
220{
221    std::lock_guard<std::recursive_mutex> guard(m_mutex);
222    for (const auto &bp_sp : m_breakpoints)
223        bp_sp->ModuleReplaced (old_module_sp, new_module_sp);
224
225}
226
227void
228BreakpointList::ClearAllBreakpointSites ()
229{
230    std::lock_guard<std::recursive_mutex> guard(m_mutex);
231    for (const auto &bp_sp : m_breakpoints)
232        bp_sp->ClearAllBreakpointSites ();
233
234}
235
236void
237BreakpointList::GetListMutex(std::unique_lock<std::recursive_mutex> &lock)
238{
239    lock = std::unique_lock<std::recursive_mutex>(m_mutex);
240}
241