Change the Thread constructor over to take a Process& rather than a ProcessSP.  We can't create Threads with a NULL ProcessSP, so it makes no sense to use the SP.
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>


git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@165640 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/API/SBThread.cpp b/source/API/SBThread.cpp
index 5a09dcc..f895a3d 100644
--- a/source/API/SBThread.cpp
+++ b/source/API/SBThread.cpp
@@ -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"
@@ -39,6 +40,12 @@
 using namespace lldb;
 using namespace lldb_private;
 
+const char *
+SBThread::GetBroadcasterClassName ()
+{
+    return Thread::GetStaticBroadcasterClass().AsCString();
+}
+
 //----------------------------------------------------------------------
 // Constructors
 //----------------------------------------------------------------------
@@ -1123,6 +1130,24 @@
     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 @@
 }
 
 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();
diff --git a/source/Commands/CommandObjectFrame.cpp b/source/Commands/CommandObjectFrame.cpp
index 0ac8e92..eab0d02 100644
--- a/source/Commands/CommandObjectFrame.cpp
+++ b/source/Commands/CommandObjectFrame.cpp
@@ -265,8 +265,9 @@
                     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 ());
diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp
index a2c3e6a..8c2be37 100644
--- a/source/Commands/CommandObjectThread.cpp
+++ b/source/Commands/CommandObjectThread.cpp
@@ -1338,7 +1338,8 @@
                 
         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 @@
             return false;
         }
 
-        thread_sp->GetStatus(result.GetOutputStream(), 0, 1, 1);
         result.SetStatus (eReturnStatusSuccessFinishResult);
         return true;
     }
diff --git a/source/Plugins/OperatingSystem/Darwin-Kernel/OperatingSystemDarwinKernel.cpp b/source/Plugins/OperatingSystem/Darwin-Kernel/OperatingSystemDarwinKernel.cpp
index b1e6830..93e6933 100644
--- a/source/Plugins/OperatingSystem/Darwin-Kernel/OperatingSystemDarwinKernel.cpp
+++ b/source/Plugins/OperatingSystem/Darwin-Kernel/OperatingSystemDarwinKernel.cpp
@@ -249,7 +249,7 @@
 
         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);
 
diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index 8de0f10..c5e3f8a 100644
--- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -188,7 +188,7 @@
                 
                 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));
diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index 8f7021a..ac09a55 100644
--- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -419,7 +419,7 @@
     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;
diff --git a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
index 150c314..567658d 100644
--- a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
@@ -37,8 +37,8 @@
 // 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)
diff --git a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h
index 97f5f8a..5454f2b 100644
--- a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h
+++ b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h
@@ -20,7 +20,7 @@
 class ThreadKDP : public lldb_private::Thread
 {
 public:
-    ThreadKDP (const lldb::ProcessSP &process_sp, 
+    ThreadKDP (lldb_private::Process &process,
                lldb::tid_t tid);
 
     virtual
diff --git a/source/Plugins/Process/Utility/ThreadMemory.cpp b/source/Plugins/Process/Utility/ThreadMemory.cpp
index 10c3a90..9e4c6d6 100644
--- a/source/Plugins/Process/Utility/ThreadMemory.cpp
+++ b/source/Plugins/Process/Utility/ThreadMemory.cpp
@@ -17,10 +17,10 @@
 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 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()
diff --git a/source/Plugins/Process/Utility/ThreadMemory.h b/source/Plugins/Process/Utility/ThreadMemory.h
index c1603d4..1880c5a 100644
--- a/source/Plugins/Process/Utility/ThreadMemory.h
+++ b/source/Plugins/Process/Utility/ThreadMemory.h
@@ -17,11 +17,11 @@
 {
 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);
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 1cc1009..215e885 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1338,7 +1338,7 @@
             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 @@
                     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);
                     }
                 }
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 95e4a99..b63b42d 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -32,15 +32,15 @@
 // 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());
 }
 
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
index 3eb6295..375b7a5 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -21,7 +21,7 @@
 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 ();
diff --git a/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/source/Plugins/Process/mach-core/ProcessMachCore.cpp
index 255f46b..5b34614 100644
--- a/source/Plugins/Process/mach-core/ProcessMachCore.cpp
+++ b/source/Plugins/Process/mach-core/ProcessMachCore.cpp
@@ -344,7 +344,7 @@
             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);
             }
         }
diff --git a/source/Plugins/Process/mach-core/ThreadMachCore.cpp b/source/Plugins/Process/mach-core/ThreadMachCore.cpp
index 3568dc7..001cda1 100644
--- a/source/Plugins/Process/mach-core/ThreadMachCore.cpp
+++ b/source/Plugins/Process/mach-core/ThreadMachCore.cpp
@@ -36,8 +36,8 @@
 // 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),
diff --git a/source/Plugins/Process/mach-core/ThreadMachCore.h b/source/Plugins/Process/mach-core/ThreadMachCore.h
index 497620c..a2d3b7a 100644
--- a/source/Plugins/Process/mach-core/ThreadMachCore.h
+++ b/source/Plugins/Process/mach-core/ThreadMachCore.h
@@ -19,7 +19,7 @@
 class ThreadMachCore : public lldb_private::Thread
 {
 public:
-    ThreadMachCore (const lldb::ProcessSP &process_sp,
+    ThreadMachCore (lldb_private::Process &process,
                     lldb::tid_t tid);
 
     virtual
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index 9fbf08b..8a89687 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -58,7 +58,7 @@
 //----------------------------------------------------------------------
 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),
diff --git a/source/Target/TargetList.cpp b/source/Target/TargetList.cpp
index 94f0d7e..3f24dd6 100644
--- a/source/Target/TargetList.cpp
+++ b/source/Target/TargetList.cpp
@@ -38,7 +38,7 @@
 // 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)
diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp
index e002ec9..5a48a0a 100644
--- a/source/Target/Thread.cpp
+++ b/source/Target/Thread.cpp
@@ -136,13 +136,112 @@
     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 @@
     if (log)
         log->Printf ("%p Thread::Thread(tid = 0x%4.4llx)", this, GetID());
 
+    CheckInWithManager();
     QueueFundamentalPlan(true);
 }
 
@@ -186,6 +286,38 @@
     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 @@
 
 
 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 @@
         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->DiscardThreadPlans(true);
         thread->ClearStackFrames();
+        if (broadcast && EventTypeHasListeners(eBroadcastBitStackChanged))
+            BroadcastEvent(eBroadcastBitStackChanged, new ThreadEventData (this->shared_from_this()));
         return return_error;
     }
     else