Change the Thread constructor over to take a Process& rather than a ProcessSP. We...
authorJim Ingham <jingham@apple.com>
Wed, 10 Oct 2012 18:32:14 +0000 (18:32 +0000)
committerJim Ingham <jingham@apple.com>
Wed, 10 Oct 2012 18:32:14 +0000 (18:32 +0000)
Then make the Thread a Broadcaster, and get it to broadcast when the selected frame is changed (but only from the Command Line) and when Thread::ReturnFromFrame
changes the stack.
Made the Driver use this notification to print the new thread status rather than doing it in the command.
Fixed a few places where people were setting their broadcaster class by hand rather than using the static broadcaster class call.

<rdar://problem/12383087>

llvm-svn: 165640

26 files changed:
lldb/include/lldb/API/SBEvent.h
lldb/include/lldb/API/SBThread.h
lldb/include/lldb/Core/Broadcaster.h
lldb/include/lldb/Target/Thread.h
lldb/scripts/Python/interface/SBThread.i
lldb/source/API/SBThread.cpp
lldb/source/Commands/CommandObjectFrame.cpp
lldb/source/Commands/CommandObjectThread.cpp
lldb/source/Plugins/OperatingSystem/Darwin-Kernel/OperatingSystemDarwinKernel.cpp
lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h
lldb/source/Plugins/Process/Utility/ThreadMemory.cpp
lldb/source/Plugins/Process/Utility/ThreadMemory.h
lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp
lldb/source/Plugins/Process/mach-core/ThreadMachCore.h
lldb/source/Target/Target.cpp
lldb/source/Target/TargetList.cpp
lldb/source/Target/Thread.cpp
lldb/tools/driver/Driver.cpp
lldb/tools/driver/Driver.h

index a24e556..f116060 100644 (file)
@@ -74,6 +74,7 @@ protected:
     friend class SBBreakpoint;
     friend class SBDebugger;
     friend class SBProcess;
+    friend class SBThread;
 
     SBEvent (lldb::EventSP &event_sp);
 
index be67526..947ef14 100644 (file)
@@ -21,6 +21,17 @@ class SBFrame;
 class SBThread
 {
 public:
+    enum
+    {
+        eBroadcastBitStackChanged           = (1 << 0),
+        eBroadcastBitThreadSuspended        = (1 << 1),
+        eBroadcastBitThreadResumed          = (1 << 2),
+        eBroadcastBitSelectedFrameChanged  = (1 << 3)
+    };
+
+    static const char *
+    GetBroadcasterClassName ();
+    
     SBThread ();
 
     SBThread (const lldb::SBThread &thread);
@@ -146,6 +157,15 @@ public:
 
     lldb::SBFrame
     SetSelectedFrame (uint32_t frame_idx);
+    
+    static bool
+    EventIsThreadEvent (const SBEvent &event);
+    
+    static SBFrame
+    GetStackFrameFromEvent (const SBEvent &event);
+    
+    static SBThread
+    GetThreadFromEvent (const SBEvent &event);
 
     lldb::SBProcess
     GetProcess ();
@@ -161,6 +181,9 @@ public:
 
     bool
     GetDescription (lldb::SBStream &description) const;
+    
+    bool
+    GetStatus (lldb::SBStream &status) const;
 
 protected:
     friend class SBBreakpoint;
index d144b1c..907132b 100644 (file)
@@ -430,6 +430,10 @@ public:
     void
     RestoreBroadcaster ();
     
+    // This needs to be filled in if you are going to register the broadcaster with the broadcaster
+    // manager and do broadcaster class matching.
+    // FIXME: Probably should make a ManagedBroadcaster subclass with all the bits needed to work
+    // with the BroadcasterManager, so that it is clearer how to add one.
     virtual ConstString &GetBroadcasterClass() const;
     
     BroadcasterManager *GetManager();
index a509fb4..8ca0729 100644 (file)
@@ -12,6 +12,8 @@
 
 #include "lldb/lldb-private.h"
 #include "lldb/Host/Mutex.h"
+#include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/Event.h"
 #include "lldb/Core/UserID.h"
 #include "lldb/Core/UserSettingsController.h"
 #include "lldb/Target/ExecutionContextScope.h"
@@ -47,15 +49,89 @@ public:
 
 typedef STD_SHARED_PTR(ThreadProperties) ThreadPropertiesSP;
 
-
 class Thread :
     public STD_ENABLE_SHARED_FROM_THIS(Thread),
     public ThreadProperties,
     public UserID,
-    public ExecutionContextScope
+    public ExecutionContextScope,
+    public Broadcaster
 {
+friend class ThreadEventData;
+
 public:
-    // TODO: You shouldn't just checkpoint the register state alone, so this should get 
+    //------------------------------------------------------------------
+    /// Broadcaster event bits definitions.
+    //------------------------------------------------------------------
+    enum
+    {
+        eBroadcastBitStackChanged           = (1 << 0),
+        eBroadcastBitThreadSuspended        = (1 << 1),
+        eBroadcastBitThreadResumed          = (1 << 2),
+        eBroadcastBitSelectedFrameChanged  = (1 << 3)
+    };
+
+    static ConstString &GetStaticBroadcasterClass ();
+    
+    virtual ConstString &GetBroadcasterClass() const
+    {
+        return GetStaticBroadcasterClass();
+    }
+    
+    class ThreadEventData :
+        public EventData
+    {
+    public:
+        ThreadEventData (const lldb::ThreadSP thread_sp);
+        
+        ThreadEventData (const lldb::ThreadSP thread_sp, const StackID &stack_id);
+        
+        ThreadEventData();
+        
+        virtual ~ThreadEventData();
+        
+        static const ConstString &
+        GetFlavorString ();
+
+        virtual const ConstString &
+        GetFlavor () const
+        {
+            return ThreadEventData::GetFlavorString ();
+        }
+        
+        virtual void
+        Dump (Stream *s) const;
+    
+        static const ThreadEventData *
+        GetEventDataFromEvent (const Event *event_ptr);
+        
+        static lldb::ThreadSP
+        GetThreadFromEvent (const Event *event_ptr);
+        
+        static StackID
+        GetStackIDFromEvent (const Event *event_ptr);
+        
+        static lldb::StackFrameSP
+        GetStackFrameFromEvent (const Event *event_ptr);
+        
+        lldb::ThreadSP
+        GetThread () const
+        {
+            return m_thread_sp;
+        }
+        
+        StackID
+        GetStackID () const
+        {
+            return m_stack_id;
+        }
+    
+    private:
+        lldb::ThreadSP m_thread_sp;
+        StackID        m_stack_id;
+    DISALLOW_COPY_AND_ASSIGN (ThreadEventData);
+    };
+    
+    // TODO: You shouldn't just checkpoint the register state alone, so this should get
     // moved to protected.  To do that ThreadStateCheckpoint needs to be returned as a token...
     class RegisterCheckpoint
     {
@@ -141,7 +217,7 @@ public:
     static const ThreadPropertiesSP &
     GetGlobalProperties();
 
-    Thread (const lldb::ProcessSP &process_sp, lldb::tid_t tid);
+    Thread (Process &process, lldb::tid_t tid);
     virtual ~Thread();
 
     lldb::ProcessSP
@@ -289,10 +365,10 @@ public:
     }
     
     Error
-    ReturnFromFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp);
+    ReturnFromFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp, bool broadcast = false);
     
     Error
-    ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp);
+    ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp, bool broadcast = false);
     
     virtual lldb::StackFrameSP
     GetFrameWithStackID (const StackID &stack_id)
@@ -314,16 +390,10 @@ public:
     }
 
     uint32_t
-    SetSelectedFrame (lldb_private::StackFrame *frame)
-    {
-        return GetStackFrameList()->SetSelectedFrame(frame);
-    }
+    SetSelectedFrame (lldb_private::StackFrame *frame, bool broadcast = false);
 
     bool
-    SetSelectedFrameByIndex (uint32_t frame_idx)
-    {
-        return GetStackFrameList()->SetSelectedFrameByIndex(frame_idx);
-    }
+    SetSelectedFrameByIndex (uint32_t frame_idx, bool broadcast = false);
 
     void
     SetDefaultFileAndLineToSelectedFrame()
@@ -557,6 +627,9 @@ private:
     bool
     PlanIsBasePlan (ThreadPlan *plan_ptr);
     
+    void
+    BroadcastSelectedFrameChange(StackID &new_frame_id);
+    
 public:
 
     //------------------------------------------------------------------
index 7c5d9f5..76a014a 100644 (file)
@@ -46,6 +46,15 @@ public:
     SBThread (const lldb::SBThread &thread);
 
    ~SBThread();
+    
+    static bool
+    EventIsThreadEvent (const SBEvent &event);
+    
+    static SBFrame
+    GetStackFrameFromEvent (const SBEvent &event);
+    
+    static SBThread
+    GetThreadFromEvent (const SBEvent &event);
 
     bool
     IsValid() const;
@@ -183,6 +192,9 @@ public:
     bool
     GetDescription (lldb::SBStream &description) const;
     
+    bool
+    GetStatus (lldb::SBStream &status) const;
+    
     %pythoncode %{
         class frames_access(object):
             '''A helper object that will lazily hand out frames for a thread when supplied an index.'''
index 5a09dcc..f895a3d 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "lldb/API/SBAddress.h"
 #include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBEvent.h"
 #include "lldb/API/SBFrame.h"
 #include "lldb/API/SBProcess.h"
 #include "lldb/API/SBValue.h"
 using namespace lldb;
 using namespace lldb_private;
 
+const char *
+SBThread::GetBroadcasterClassName ()
+{
+    return Thread::GetStaticBroadcasterClass().AsCString();
+}
+
 //----------------------------------------------------------------------
 // Constructors
 //----------------------------------------------------------------------
@@ -1123,6 +1130,24 @@ SBThread::SetSelectedFrame (uint32_t idx)
     return sb_frame;
 }
 
+bool
+SBThread::EventIsThreadEvent (const SBEvent &event)
+{
+    return Thread::ThreadEventData::GetEventDataFromEvent(event.get()) != NULL;
+}
+
+SBFrame
+SBThread::GetStackFrameFromEvent (const SBEvent &event)
+{
+    return Thread::ThreadEventData::GetStackFrameFromEvent (event.get());
+
+}
+
+SBThread
+SBThread::GetThreadFromEvent (const SBEvent &event)
+{
+    return Thread::ThreadEventData::GetThreadFromEvent (event.get());
+}
 
 bool
 SBThread::operator == (const SBThread &rhs) const
@@ -1137,6 +1162,22 @@ SBThread::operator != (const SBThread &rhs) const
 }
 
 bool
+SBThread::GetStatus (SBStream &status) const
+{
+    Stream &strm = status.ref();
+
+    ExecutionContext exe_ctx (m_opaque_sp.get());
+    if (exe_ctx.HasThreadScope())
+    {
+        exe_ctx.GetThreadPtr()->GetStatus(strm, 0, 1, 1);
+    }
+    else
+        strm.PutCString ("No status");
+    
+    return true;
+}
+
+bool
 SBThread::GetDescription (SBStream &description) const
 {
     Stream &strm = description.ref();
index 0ac8e92..eab0d02 100644 (file)
@@ -265,8 +265,9 @@ protected:
                     m_options.GenerateOptionUsage (result.GetErrorStream(), this);
                 }
             }
-                
-            bool success = thread->SetSelectedFrameByIndex (frame_idx);
+
+            const bool broadcast = true;
+            bool success = thread->SetSelectedFrameByIndex (frame_idx, broadcast);
             if (success)
             {
                 exe_ctx.SetFrameSP(thread->GetSelectedFrame ());
index a2c3e6a..8c2be37 100644 (file)
@@ -1338,7 +1338,8 @@ protected:
                 
         Error error;
         ThreadSP thread_sp = exe_ctx.GetThreadSP();
-        error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp);
+        const bool broadcast = true;
+        error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp, broadcast);
         if (!error.Success())
         {
             result.AppendErrorWithFormat("Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString());
@@ -1346,7 +1347,6 @@ protected:
             return false;
         }
 
-        thread_sp->GetStatus(result.GetOutputStream(), 0, 1, 1);
         result.SetStatus (eReturnStatusSuccessFinishResult);
         return true;
     }
index b1e6830..93e6933 100644 (file)
@@ -249,7 +249,7 @@ OperatingSystemDarwinKernel::UpdateThreadList (ThreadList &old_thread_list, Thre
 
         ThreadSP thread_sp (old_thread_list.FindThreadByID (tid, false));
         if (!thread_sp)
-            thread_sp.reset (new ThreadMemory (m_process->shared_from_this(), tid, valobj_sp));
+            thread_sp.reset (new ThreadMemory (*m_process, tid, valobj_sp));
 
         new_thread_list.AddThread(thread_sp);
 
index 8de0f10..c5e3f8a 100644 (file)
@@ -188,7 +188,7 @@ OperatingSystemPython::UpdateThreadList (ThreadList &old_thread_list, ThreadList
                 
                 ThreadSP thread_sp (old_thread_list.FindThreadByID (tid, false));
                 if (!thread_sp)
-                    thread_sp.reset (new ThreadMemory (m_process->shared_from_this(),
+                    thread_sp.reset (new ThreadMemory (*m_process,
                                                        tid,
                                                        name,
                                                        queue));
index 8f7021a..ac09a55 100644 (file)
@@ -419,7 +419,7 @@ ProcessKDP::GetKernelThread(ThreadList &old_thread_list, ThreadList &new_thread_
     ThreadSP thread_sp (old_thread_list.FindThreadByID (kernel_tid, false));
     if (!thread_sp)
     {
-        thread_sp.reset(new ThreadKDP (shared_from_this(), kernel_tid));
+        thread_sp.reset(new ThreadKDP (*this, kernel_tid));
         new_thread_list.AddThread(thread_sp);
     }
     return thread_sp;
index 150c314..567658d 100644 (file)
@@ -37,8 +37,8 @@ using namespace lldb_private;
 // Thread Registers
 //----------------------------------------------------------------------
 
-ThreadKDP::ThreadKDP (const lldb::ProcessSP &process_sp, lldb::tid_t tid) :
-    Thread(process_sp, tid),
+ThreadKDP::ThreadKDP (Process &process, lldb::tid_t tid) :
+    Thread(process, tid),
     m_thread_name (),
     m_dispatch_queue_name (),
     m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS)
index 97f5f8a..5454f2b 100644 (file)
@@ -20,7 +20,7 @@ class ProcessKDP;
 class ThreadKDP : public lldb_private::Thread
 {
 public:
-    ThreadKDP (const lldb::ProcessSP &process_sp, 
+    ThreadKDP (lldb_private::Process &process,
                lldb::tid_t tid);
 
     virtual
index 10c3a90..9e4c6d6 100644 (file)
 using namespace lldb;
 using namespace lldb_private;
 
-ThreadMemory::ThreadMemory (const ProcessSP &process_sp, 
+ThreadMemory::ThreadMemory (Process &process,
                               tid_t tid, 
                               const ValueObjectSP &thread_info_valobj_sp) :
-    Thread (process_sp, tid),
+    Thread (process, tid),
     m_thread_info_valobj_sp (thread_info_valobj_sp),
     m_name(),
     m_queue()
@@ -28,11 +28,11 @@ ThreadMemory::ThreadMemory (const ProcessSP &process_sp,
 }
 
 
-ThreadMemory::ThreadMemory (const lldb::ProcessSP &process_sp,
+ThreadMemory::ThreadMemory (Process &process,
                             lldb::tid_t tid,
                             const char *name,
                             const char *queue) :
-    Thread (process_sp, tid),
+    Thread (process, tid),
     m_thread_info_valobj_sp (),
     m_name(),
     m_queue()
index c1603d4..1880c5a 100644 (file)
@@ -17,11 +17,11 @@ class ThreadMemory :
 {
 public:
 
-    ThreadMemory (const lldb::ProcessSP &process_sp, 
+    ThreadMemory (lldb_private::Process &process,
                   lldb::tid_t tid,
                   const lldb::ValueObjectSP &thread_info_valobj_sp);
 
-    ThreadMemory (const lldb::ProcessSP &process_sp,
+    ThreadMemory (lldb_private::Process &process,
                   lldb::tid_t tid,
                   const char *name,
                   const char *queue);
index 1cc1009..215e885 100644 (file)
@@ -1338,7 +1338,7 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new
             tid_t tid = m_thread_ids[i];
             ThreadSP thread_sp (old_thread_list.FindThreadByID (tid, false));
             if (!thread_sp)
-                thread_sp.reset (new ThreadGDBRemote (shared_from_this(), tid));
+                thread_sp.reset (new ThreadGDBRemote (*this, tid));
             new_thread_list.AddThread(thread_sp);
         }
     }
@@ -1405,7 +1405,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
                     if (!thread_sp)
                     {
                         // Create the thread if we need to
-                        thread_sp.reset (new ThreadGDBRemote (shared_from_this(), tid));
+                        thread_sp.reset (new ThreadGDBRemote (*this, tid));
                         m_thread_list.AddThread(thread_sp);
                     }
                 }
index 95e4a99..b63b42d 100644 (file)
@@ -32,15 +32,15 @@ using namespace lldb_private;
 // Thread Registers
 //----------------------------------------------------------------------
 
-ThreadGDBRemote::ThreadGDBRemote (const ProcessSP &process_sp, lldb::tid_t tid) :
-    Thread(process_sp, tid),
+ThreadGDBRemote::ThreadGDBRemote (Process &process, lldb::tid_t tid) :
+    Thread(process, tid),
     m_thread_name (),
     m_dispatch_queue_name (),
     m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS)
 {
     ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "%p: ThreadGDBRemote::ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", 
                                this, 
-                               process_sp ? process_sp->GetID() : LLDB_INVALID_PROCESS_ID, 
+                               process.GetID(),
                                GetID());
 }
 
index 3eb6295..375b7a5 100644 (file)
@@ -21,7 +21,7 @@ class ProcessGDBRemote;
 class ThreadGDBRemote : public lldb_private::Thread
 {
 public:
-    ThreadGDBRemote (const lldb::ProcessSP &process_sp, lldb::tid_t tid);
+    ThreadGDBRemote (lldb_private::Process &process, lldb::tid_t tid);
 
     virtual
     ~ThreadGDBRemote ();
index 255f46b..5b34614 100644 (file)
@@ -344,7 +344,7 @@ ProcessMachCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_
             const uint32_t num_threads = core_objfile->GetNumThreadContexts ();
             for (lldb::tid_t tid = 0; tid < num_threads; ++tid)
             {
-                ThreadSP thread_sp(new ThreadMachCore (shared_from_this(), tid));
+                ThreadSP thread_sp(new ThreadMachCore (*this, tid));
                 new_thread_list.AddThread (thread_sp);
             }
         }
index 3568dc7..001cda1 100644 (file)
@@ -36,8 +36,8 @@ using namespace lldb_private;
 // Thread Registers
 //----------------------------------------------------------------------
 
-ThreadMachCore::ThreadMachCore (const lldb::ProcessSP &process_sp, lldb::tid_t tid) :
-    Thread(process_sp, tid),
+ThreadMachCore::ThreadMachCore (Process &process, lldb::tid_t tid) :
+    Thread(process, tid),
     m_thread_name (),
     m_dispatch_queue_name (),
     m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS),
index 497620c..a2d3b7a 100644 (file)
@@ -19,7 +19,7 @@ class ProcessMachCore;
 class ThreadMachCore : public lldb_private::Thread
 {
 public:
-    ThreadMachCore (const lldb::ProcessSP &process_sp,
+    ThreadMachCore (lldb_private::Process &process,
                     lldb::tid_t tid);
 
     virtual
index 9fbf08b..8a89687 100644 (file)
@@ -58,7 +58,7 @@ Target::GetStaticBroadcasterClass ()
 //----------------------------------------------------------------------
 Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::PlatformSP &platform_sp) :
     TargetProperties (this),
-    Broadcaster (&debugger, "lldb.target"),
+    Broadcaster (&debugger, Target::GetStaticBroadcasterClass().AsCString()),
     ExecutionContextScope (),
     m_debugger (debugger),
     m_platform_sp (platform_sp),
index 94f0d7e..3f24dd6 100644 (file)
@@ -38,7 +38,7 @@ TargetList::GetStaticBroadcasterClass ()
 // TargetList constructor
 //----------------------------------------------------------------------
 TargetList::TargetList(Debugger &debugger) :
-    Broadcaster(&debugger, "TargetList"),
+    Broadcaster(&debugger, TargetList::GetStaticBroadcasterClass().AsCString()),
     m_target_list(),
     m_target_list_mutex (Mutex::eMutexTypeRecursive),
     m_selected_target_idx (0)
index e002ec9..5a48a0a 100644 (file)
@@ -136,13 +136,112 @@ ThreadProperties::GetTraceEnabledState() const
     return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
 }
 
+//------------------------------------------------------------------
+// Thread Event Data
+//------------------------------------------------------------------
 
-Thread::Thread (const ProcessSP &process_sp, lldb::tid_t tid) :
+
+const ConstString &
+Thread::ThreadEventData::GetFlavorString ()
+{
+    static ConstString g_flavor ("Thread::ThreadEventData");
+    return g_flavor;
+}
+
+Thread::ThreadEventData::ThreadEventData (const lldb::ThreadSP thread_sp) :
+    m_thread_sp (thread_sp),
+    m_stack_id ()
+{
+}
+
+Thread::ThreadEventData::ThreadEventData (const lldb::ThreadSP thread_sp, const StackID &stack_id) :
+    m_thread_sp (thread_sp),
+    m_stack_id (stack_id)
+{
+}
+
+Thread::ThreadEventData::ThreadEventData () :
+    m_thread_sp (),
+    m_stack_id ()
+{
+}
+
+Thread::ThreadEventData::~ThreadEventData ()
+{
+}
+
+void
+Thread::ThreadEventData::Dump (Stream *s) const
+{
+
+}
+
+const Thread::ThreadEventData *
+Thread::ThreadEventData::GetEventDataFromEvent (const Event *event_ptr)
+{
+    if (event_ptr)
+    {
+        const EventData *event_data = event_ptr->GetData();
+        if (event_data && event_data->GetFlavor() == ThreadEventData::GetFlavorString())
+            return static_cast <const ThreadEventData *> (event_ptr->GetData());
+    }
+    return NULL;
+}
+
+ThreadSP
+Thread::ThreadEventData::GetThreadFromEvent (const Event *event_ptr)
+{
+    ThreadSP thread_sp;
+    const ThreadEventData *event_data = GetEventDataFromEvent (event_ptr);
+    if (event_data)
+        thread_sp = event_data->GetThread();
+    return thread_sp;
+}
+
+StackID
+Thread::ThreadEventData::GetStackIDFromEvent (const Event *event_ptr)
+{
+    StackID stack_id;
+    const ThreadEventData *event_data = GetEventDataFromEvent (event_ptr);
+    if (event_data)
+        stack_id = event_data->GetStackID();
+    return stack_id;
+}
+
+StackFrameSP
+Thread::ThreadEventData::GetStackFrameFromEvent (const Event *event_ptr)
+{
+    const ThreadEventData *event_data = GetEventDataFromEvent (event_ptr);
+    StackFrameSP frame_sp;
+    if (event_data)
+    {
+        ThreadSP thread_sp = event_data->GetThread();
+        if (thread_sp)
+        {
+            frame_sp = thread_sp->GetStackFrameList()->GetFrameWithStackID (event_data->GetStackID());
+        }
+    }
+    return frame_sp;
+}
+
+//------------------------------------------------------------------
+// Thread class
+//------------------------------------------------------------------
+
+ConstString &
+Thread::GetStaticBroadcasterClass ()
+{
+    static ConstString class_name ("lldb.thread");
+    return class_name;
+}
+
+Thread::Thread (Process &process, lldb::tid_t tid) :
     ThreadProperties (false),
     UserID (tid),
-    m_process_wp (process_sp),
+    Broadcaster(&process.GetTarget().GetDebugger(), Thread::GetStaticBroadcasterClass().AsCString()),
+    m_process_wp (process.shared_from_this()),
     m_actual_stop_info_sp (),
-    m_index_id (process_sp->GetNextThreadIndexID ()),
+    m_index_id (process.GetNextThreadIndexID ()),
     m_reg_context_sp (),
     m_state (eStateUnloaded),
     m_state_mutex (Mutex::eMutexTypeRecursive),
@@ -163,6 +262,7 @@ Thread::Thread (const ProcessSP &process_sp, lldb::tid_t tid) :
     if (log)
         log->Printf ("%p Thread::Thread(tid = 0x%4.4llx)", this, GetID());
 
+    CheckInWithManager();
     QueueFundamentalPlan(true);
 }
 
@@ -186,6 +286,38 @@ Thread::DestroyThread ()
     m_destroy_called = true;
 }
 
+void
+Thread::BroadcastSelectedFrameChange(StackID &new_frame_id)
+{
+    if (EventTypeHasListeners(eBroadcastBitSelectedFrameChanged))
+        BroadcastEvent(eBroadcastBitSelectedFrameChanged, new ThreadEventData (this->shared_from_this(), new_frame_id));
+}
+
+uint32_t
+Thread::SetSelectedFrame (lldb_private::StackFrame *frame, bool broadcast)
+{
+    uint32_t ret_value = GetStackFrameList()->SetSelectedFrame(frame);
+    if (broadcast)
+        BroadcastSelectedFrameChange(frame->GetStackID());
+    return ret_value;
+}
+
+bool
+Thread::SetSelectedFrameByIndex (uint32_t frame_idx, bool broadcast)
+{
+    StackFrameSP frame_sp(GetStackFrameList()->GetFrameAtIndex (frame_idx));
+    if (frame_sp)
+    {
+        GetStackFrameList()->SetSelectedFrame(frame_sp.get());
+        if (broadcast)
+            BroadcastSelectedFrameChange(frame_sp->GetStackID());
+        return true;
+    }
+    else
+        return false;
+}
+
+
 lldb::StopInfoSP
 Thread::GetStopInfo ()
 {
@@ -1285,7 +1417,7 @@ Thread::GetFrameWithConcreteFrameIndex (uint32_t unwind_idx)
 
 
 Error
-Thread::ReturnFromFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp)
+Thread::ReturnFromFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp, bool broadcast)
 {
     StackFrameSP frame_sp = GetStackFrameAtIndex (frame_idx);
     Error return_error;
@@ -1295,11 +1427,11 @@ Thread::ReturnFromFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return
         return_error.SetErrorStringWithFormat("Could not find frame with index %d in thread 0x%llx.", frame_idx, GetID());
     }
     
-    return ReturnFromFrame(frame_sp, return_value_sp);
+    return ReturnFromFrame(frame_sp, return_value_sp, broadcast);
 }
 
 Error
-Thread::ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp)
+Thread::ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp, bool broadcast)
 {
     Error return_error;
     
@@ -1358,6 +1490,8 @@ Thread::ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return
     {
         thread->DiscardThreadPlans(true);
         thread->ClearStackFrames();
+        if (broadcast && EventTypeHasListeners(eBroadcastBitStackChanged))
+            BroadcastEvent(eBroadcastBitStackChanged, new ThreadEventData (this->shared_from_this()));
         return return_error;
     }
     else
index 84d464f..048faff 100644 (file)
@@ -978,6 +978,25 @@ Driver::HandleProcessEvent (const SBEvent &event)
     }
 }
 
+void
+Driver::HandleThreadEvent (const SBEvent &event)
+{
+    // At present the only thread event we handle is the Frame Changed event, and all we do for that is just
+    // reprint the thread status for that thread.
+    using namespace lldb;
+    const uint32_t event_type = event.GetType();
+    if (event_type == SBThread::eBroadcastBitStackChanged)
+    {
+        SBThread thread = SBThread::GetThreadFromEvent (event);
+        if (thread.IsValid())
+        {
+            SBStream out_stream;
+            thread.GetStatus(out_stream);
+            m_io_channel_ap->OutWrite (out_stream.GetData (), out_stream.GetSize (), ASYNC);
+        }
+    }
+}
+
 //  This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
 
 bool
@@ -1268,12 +1287,15 @@ Driver::MainLoop ()
     m_debugger.PushInputReader (m_editline_reader);
 
     SBListener listener(m_debugger.GetListener());
-    listener.StartListeningForEventClass(m_debugger, 
-                                         SBTarget::GetBroadcasterClassName(), 
-                                         SBTarget::eBroadcastBitBreakpointChanged);
     if (listener.IsValid())
     {
 
+        listener.StartListeningForEventClass(m_debugger, 
+                                         SBTarget::GetBroadcasterClassName(), 
+                                         SBTarget::eBroadcastBitBreakpointChanged);
+        listener.StartListeningForEventClass(m_debugger, 
+                                         SBThread::GetBroadcasterClassName(),
+                                         SBThread::eBroadcastBitStackChanged);
         listener.StartListeningForEvents (*m_io_channel_ap,
                                           IOChannel::eBroadcastBitHasUserInput |
                                           IOChannel::eBroadcastBitUserInterrupt |
@@ -1452,6 +1474,10 @@ Driver::MainLoop ()
                         {
                             HandleBreakpointEvent (event);
                         }
+                        else if (SBThread::EventIsThreadEvent (event))
+                        {
+                            HandleThreadEvent (event);
+                        }
                         else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
                         {
                             // TODO: deprecate the eBroadcastBitQuitCommandReceived event
index 2c69b6c..16558e0 100644 (file)
@@ -65,6 +65,9 @@ public:
     void
     HandleBreakpointEvent (const lldb::SBEvent &event);
 
+    void
+    HandleThreadEvent (const lldb::SBEvent &event);
+
     lldb::SBError
     ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &do_exit);