SBQueue.cpp revision 269024
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
22using namespace lldb;
23using namespace lldb_private;
24
25namespace lldb_private
26{
27
28    class QueueImpl
29    {
30    public:
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
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
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
61        ~QueueImpl ()
62        {
63        }
64
65        bool
66        IsValid ()
67        {
68            return m_queue_wp.lock() != NULL;
69        }
70
71        void
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
82        SetQueue (const lldb::QueueSP &queue_sp)
83        {
84            Clear();
85            m_queue_wp = queue_sp;
86        }
87
88        lldb::queue_id_t
89        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
104        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 *
119        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
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
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
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
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
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
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
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
272SBQueue::SBQueue () :
273    m_opaque_sp (new QueueImpl())
274{
275}
276
277SBQueue::SBQueue (const QueueSP& queue_sp) :
278    m_opaque_sp (new QueueImpl (queue_sp))
279{
280}
281
282SBQueue::SBQueue (const SBQueue &rhs)
283{
284    if (&rhs == this)
285        return;
286
287    m_opaque_sp = rhs.m_opaque_sp;
288}
289
290const lldb::SBQueue &
291SBQueue::operator = (const lldb::SBQueue &rhs)
292{
293    m_opaque_sp = rhs.m_opaque_sp;
294    return *this;
295}
296
297SBQueue::~SBQueue()
298{
299}
300
301bool
302SBQueue::IsValid() const
303{
304    return m_opaque_sp->IsValid();
305}
306
307
308void
309SBQueue::Clear ()
310{
311    m_opaque_sp->Clear();
312}
313
314
315void
316SBQueue::SetQueue (const QueueSP& queue_sp)
317{
318    m_opaque_sp->SetQueue (queue_sp);
319}
320
321lldb::queue_id_t
322SBQueue::GetQueueID () const
323{
324    return m_opaque_sp->GetQueueID ();
325}
326
327uint32_t
328SBQueue::GetIndexID () const
329{
330    return m_opaque_sp->GetIndexID ();
331}
332
333const char *
334SBQueue::GetName () const
335{
336    return m_opaque_sp->GetName ();
337}
338
339uint32_t
340SBQueue::GetNumThreads ()
341{
342    return m_opaque_sp->GetNumThreads ();
343}
344
345SBThread
346SBQueue::GetThreadAtIndex (uint32_t idx)
347{
348    return m_opaque_sp->GetThreadAtIndex (idx);
349}
350
351
352uint32_t
353SBQueue::GetNumPendingItems ()
354{
355    return m_opaque_sp->GetNumPendingItems ();
356}
357
358SBQueueItem
359SBQueue::GetPendingItemAtIndex (uint32_t idx)
360{
361    return m_opaque_sp->GetPendingItemAtIndex (idx);
362}
363
364SBProcess
365SBQueue::GetProcess ()
366{
367    return m_opaque_sp->GetProcess();
368}
369