1 //===-- SBQueue.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/lldb-python.h"
11
12 #include "lldb/API/SBQueue.h"
13
14 #include "lldb/API/SBProcess.h"
15 #include "lldb/API/SBThread.h"
16 #include "lldb/Core/Log.h"
17 #include "lldb/Target/Process.h"
18 #include "lldb/Target/Queue.h"
19 #include "lldb/Target/QueueItem.h"
20 #include "lldb/Target/Thread.h"
21
22 using namespace lldb;
23 using namespace lldb_private;
24
25 namespace lldb_private
26 {
27
28 class QueueImpl
29 {
30 public:
QueueImpl()31 QueueImpl () :
32 m_queue_wp(),
33 m_threads(),
34 m_thread_list_fetched(false),
35 m_pending_items(),
36 m_pending_items_fetched(false)
37 {
38 }
39
QueueImpl(const lldb::QueueSP & queue_sp)40 QueueImpl (const lldb::QueueSP &queue_sp) :
41 m_queue_wp(),
42 m_threads(),
43 m_thread_list_fetched(false),
44 m_pending_items(),
45 m_pending_items_fetched(false)
46 {
47 m_queue_wp = queue_sp;
48 }
49
QueueImpl(const QueueImpl & rhs)50 QueueImpl (const QueueImpl &rhs)
51 {
52 if (&rhs == this)
53 return;
54 m_queue_wp = rhs.m_queue_wp;
55 m_threads = rhs.m_threads;
56 m_thread_list_fetched = rhs.m_thread_list_fetched;
57 m_pending_items = rhs.m_pending_items;
58 m_pending_items_fetched = rhs.m_pending_items_fetched;
59 }
60
~QueueImpl()61 ~QueueImpl ()
62 {
63 }
64
65 bool
IsValid()66 IsValid ()
67 {
68 return m_queue_wp.lock() != NULL;
69 }
70
71 void
Clear()72 Clear ()
73 {
74 m_queue_wp.reset();
75 m_thread_list_fetched = false;
76 m_threads.clear();
77 m_pending_items_fetched = false;
78 m_pending_items.clear();
79 }
80
81 void
SetQueue(const lldb::QueueSP & queue_sp)82 SetQueue (const lldb::QueueSP &queue_sp)
83 {
84 Clear();
85 m_queue_wp = queue_sp;
86 }
87
88 lldb::queue_id_t
GetQueueID() const89 GetQueueID () const
90 {
91 lldb::queue_id_t result = LLDB_INVALID_QUEUE_ID;
92 lldb::QueueSP queue_sp = m_queue_wp.lock();
93 if (queue_sp)
94 {
95 result = queue_sp->GetID();
96 }
97 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
98 if (log)
99 log->Printf ("SBQueue(%p)::GetQueueID () => 0x%" PRIx64, this, result);
100 return result;
101 }
102
103 uint32_t
GetIndexID() const104 GetIndexID () const
105 {
106 uint32_t result = LLDB_INVALID_INDEX32;
107 lldb::QueueSP queue_sp = m_queue_wp.lock();
108 if (queue_sp)
109 {
110 result = queue_sp->GetIndexID();
111 }
112 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
113 if (log)
114 log->Printf ("SBQueueImpl(%p)::GetIndexID () => %d", this, result);
115 return result;
116 }
117
118 const char *
GetName() const119 GetName () const
120 {
121 const char *name = NULL;
122 lldb::QueueSP queue_sp = m_queue_wp.lock ();
123 if (queue_sp.get())
124 {
125 name = queue_sp->GetName();
126 }
127
128 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
129 if (log)
130 log->Printf ("SBQueueImpl(%p)::GetName () => %s", this, name ? name : "NULL");
131
132 return name;
133 }
134
135 void
FetchThreads()136 FetchThreads ()
137 {
138 if (m_thread_list_fetched == false)
139 {
140 lldb::QueueSP queue_sp = m_queue_wp.lock();
141 if (queue_sp)
142 {
143 Process::StopLocker stop_locker;
144 if (stop_locker.TryLock (&queue_sp->GetProcess()->GetRunLock()))
145 {
146 const std::vector<ThreadSP> thread_list(queue_sp->GetThreads());
147 m_thread_list_fetched = true;
148 const uint32_t num_threads = thread_list.size();
149 for (uint32_t idx = 0; idx < num_threads; ++idx)
150 {
151 ThreadSP thread_sp = thread_list[idx];
152 if (thread_sp && thread_sp->IsValid())
153 {
154 m_threads.push_back (thread_sp);
155 }
156 }
157 }
158 }
159 }
160 }
161
162 void
FetchItems()163 FetchItems ()
164 {
165 if (m_pending_items_fetched == false)
166 {
167 QueueSP queue_sp = m_queue_wp.lock();
168 if (queue_sp)
169 {
170 Process::StopLocker stop_locker;
171 if (stop_locker.TryLock (&queue_sp->GetProcess()->GetRunLock()))
172 {
173 const std::vector<QueueItemSP> queue_items(queue_sp->GetPendingItems());
174 m_pending_items_fetched = true;
175 const uint32_t num_pending_items = queue_items.size();
176 for (uint32_t idx = 0; idx < num_pending_items; ++idx)
177 {
178 QueueItemSP item = queue_items[idx];
179 if (item && item->IsValid())
180 {
181 m_pending_items.push_back (item);
182 }
183 }
184 }
185 }
186 }
187 }
188
189 uint32_t
GetNumThreads()190 GetNumThreads ()
191 {
192 uint32_t result = 0;
193
194 FetchThreads();
195 if (m_thread_list_fetched)
196 {
197 result = m_threads.size();
198 }
199 return result;
200 }
201
202 lldb::SBThread
GetThreadAtIndex(uint32_t idx)203 GetThreadAtIndex (uint32_t idx)
204 {
205 FetchThreads();
206
207 SBThread sb_thread;
208 QueueSP queue_sp = m_queue_wp.lock();
209 if (queue_sp && idx < m_threads.size())
210 {
211 ProcessSP process_sp = queue_sp->GetProcess();
212 if (process_sp)
213 {
214 ThreadSP thread_sp = m_threads[idx].lock();
215 if (thread_sp)
216 {
217 sb_thread.SetThread (thread_sp);
218 }
219 }
220 }
221 return sb_thread;
222 }
223
224
225 uint32_t
GetNumPendingItems()226 GetNumPendingItems ()
227 {
228 uint32_t result = 0;
229 FetchItems();
230
231 if (m_pending_items_fetched)
232 {
233 result = m_pending_items.size();
234 }
235 return result;
236 }
237
238 lldb::SBQueueItem
GetPendingItemAtIndex(uint32_t idx)239 GetPendingItemAtIndex (uint32_t idx)
240 {
241 SBQueueItem result;
242 FetchItems();
243 if (m_pending_items_fetched && idx < m_pending_items.size())
244 {
245 result.SetQueueItem (m_pending_items[idx]);
246 }
247 return result;
248 }
249
250 lldb::SBProcess
GetProcess()251 GetProcess ()
252 {
253 SBProcess result;
254 QueueSP queue_sp = m_queue_wp.lock();
255 if (queue_sp)
256 {
257 result.SetSP (queue_sp->GetProcess());
258 }
259 return result;
260 }
261
262 private:
263 lldb::QueueWP m_queue_wp;
264 std::vector<lldb::ThreadWP> m_threads; // threads currently executing this queue's items
265 bool m_thread_list_fetched; // have we tried to fetch the threads list already?
266 std::vector<lldb::QueueItemSP> m_pending_items; // items currently enqueued
267 bool m_pending_items_fetched; // have we tried to fetch the item list already?
268 };
269
270 }
271
SBQueue()272 SBQueue::SBQueue () :
273 m_opaque_sp (new QueueImpl())
274 {
275 }
276
SBQueue(const QueueSP & queue_sp)277 SBQueue::SBQueue (const QueueSP& queue_sp) :
278 m_opaque_sp (new QueueImpl (queue_sp))
279 {
280 }
281
SBQueue(const SBQueue & rhs)282 SBQueue::SBQueue (const SBQueue &rhs)
283 {
284 if (&rhs == this)
285 return;
286
287 m_opaque_sp = rhs.m_opaque_sp;
288 }
289
290 const lldb::SBQueue &
operator =(const lldb::SBQueue & rhs)291 SBQueue::operator = (const lldb::SBQueue &rhs)
292 {
293 m_opaque_sp = rhs.m_opaque_sp;
294 return *this;
295 }
296
~SBQueue()297 SBQueue::~SBQueue()
298 {
299 }
300
301 bool
IsValid() const302 SBQueue::IsValid() const
303 {
304 return m_opaque_sp->IsValid();
305 }
306
307
308 void
Clear()309 SBQueue::Clear ()
310 {
311 m_opaque_sp->Clear();
312 }
313
314
315 void
SetQueue(const QueueSP & queue_sp)316 SBQueue::SetQueue (const QueueSP& queue_sp)
317 {
318 m_opaque_sp->SetQueue (queue_sp);
319 }
320
321 lldb::queue_id_t
GetQueueID() const322 SBQueue::GetQueueID () const
323 {
324 return m_opaque_sp->GetQueueID ();
325 }
326
327 uint32_t
GetIndexID() const328 SBQueue::GetIndexID () const
329 {
330 return m_opaque_sp->GetIndexID ();
331 }
332
333 const char *
GetName() const334 SBQueue::GetName () const
335 {
336 return m_opaque_sp->GetName ();
337 }
338
339 uint32_t
GetNumThreads()340 SBQueue::GetNumThreads ()
341 {
342 return m_opaque_sp->GetNumThreads ();
343 }
344
345 SBThread
GetThreadAtIndex(uint32_t idx)346 SBQueue::GetThreadAtIndex (uint32_t idx)
347 {
348 return m_opaque_sp->GetThreadAtIndex (idx);
349 }
350
351
352 uint32_t
GetNumPendingItems()353 SBQueue::GetNumPendingItems ()
354 {
355 return m_opaque_sp->GetNumPendingItems ();
356 }
357
358 SBQueueItem
GetPendingItemAtIndex(uint32_t idx)359 SBQueue::GetPendingItemAtIndex (uint32_t idx)
360 {
361 return m_opaque_sp->GetPendingItemAtIndex (idx);
362 }
363
364 SBProcess
GetProcess()365 SBQueue::GetProcess ()
366 {
367 return m_opaque_sp->GetProcess();
368 }
369