The LLDB API (lldb::SB*) is now thread safe!



git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@122262 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/API/SBDebugger.cpp b/source/API/SBDebugger.cpp
index a2d836f..eea2ba2 100644
--- a/source/API/SBDebugger.cpp
+++ b/source/API/SBDebugger.cpp
@@ -216,6 +216,11 @@
 {
     if (m_opaque_sp)
     {
+        TargetSP target_sp (m_opaque_sp->GetSelectedTarget());
+        Mutex::Locker api_locker;
+        if (target_sp)
+            api_locker.Reset(target_sp->GetAPIMutex().GetMutex());
+
         SBCommandInterpreter sb_interpreter(GetCommandInterpreter ());
         SBCommandReturnObject result;
 
@@ -262,110 +267,41 @@
 void
 SBDebugger::HandleProcessEvent (const SBProcess &process, const SBEvent &event, FILE *out, FILE *err)
 {
-     const uint32_t event_type = event.GetType();
-     char stdio_buffer[1024];
-     size_t len;
+    if (!process.IsValid())
+        return;
 
-     if (event_type & Process::eBroadcastBitSTDOUT)
-     {
-         while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
-             if (out != NULL)
-                 ::fwrite (stdio_buffer, 1, len, out);
-     }
-     else if (event_type & Process::eBroadcastBitSTDERR)
-     {
-         while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
-             if (out != NULL)
-                 ::fwrite (stdio_buffer, 1, len, out);
-     }
-     else if (event_type & Process::eBroadcastBitStateChanged)
-     {
-         // Drain any stdout messages.
-         while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
-             if (out != NULL)
-                 ::fwrite (stdio_buffer, 1, len, out);
+    const uint32_t event_type = event.GetType();
+    char stdio_buffer[1024];
+    size_t len;
 
-         // Drain any stderr messages.
-         while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
-             if (out != NULL)
-                 ::fwrite (stdio_buffer, 1, len, out);
-
-         StateType event_state = SBProcess::GetStateFromEvent (event);
-
-         if (event_state == eStateInvalid)
-             return;
-
-         bool is_stopped = StateIsStoppedState (event_state);
-         if (!is_stopped)
-             process.ReportEventState (event, out);
-   }
-}
-
-void
-SBDebugger::UpdateSelectedThread (SBProcess &process)
-{
-    if (process.IsValid())
+    Mutex::Locker api_locker (process.GetTarget()->GetAPIMutex());
+    
+    if (event_type & (Process::eBroadcastBitSTDOUT | Process::eBroadcastBitStateChanged))
     {
-        SBThread curr_thread = process.GetSelectedThread ();
-        SBThread thread;
-        StopReason curr_thread_stop_reason = eStopReasonInvalid;
-        if (curr_thread.IsValid())
-        {
-            if (curr_thread.GetStopReason() != eStopReasonInvalid)
-                curr_thread_stop_reason = curr_thread.GetStopReason ();
-        }
-
-        if (! curr_thread.IsValid()
-            || curr_thread_stop_reason == eStopReasonInvalid
-            || curr_thread_stop_reason == eStopReasonNone)
-          {
-            // Prefer a thread that has just completed its plan over another thread as current thread.
-            SBThread plan_thread;
-            SBThread other_thread;
-            const size_t num_threads = process.GetNumThreads ();
-            size_t i;
-            for (i = 0; i < num_threads; ++i)
-            {
-                thread = process.GetThreadAtIndex(i);
-                if (thread.GetStopReason () != eStopReasonInvalid)
-                {
-                    switch (thread.GetStopReason ())
-                    {
-                        default:
-                        case eStopReasonInvalid:
-                        case eStopReasonNone:
-                            break;
-
-                        case eStopReasonTrace:
-                        case eStopReasonBreakpoint:
-                        case eStopReasonWatchpoint:
-                        case eStopReasonSignal:
-                        case eStopReasonException:
-                            if (! other_thread.IsValid())
-                                other_thread = thread;
-                            break;
-                        case eStopReasonPlanComplete:
-                            if (! plan_thread.IsValid())
-                                plan_thread = thread;
-                            break;
-                    }
-                }
-            }
-            if (plan_thread.IsValid())
-                process.SetSelectedThreadByID (plan_thread.GetThreadID());
-            else if (other_thread.IsValid())
-                process.SetSelectedThreadByID (other_thread.GetThreadID());
-            else
-            {
-                if (curr_thread.IsValid())
-                    thread = curr_thread;
-                else
-                    thread = process.GetThreadAtIndex(0);
-
-                if (thread.IsValid())
-                    process.SetSelectedThreadByID (thread.GetThreadID());
-            }
-        }
+        // Drain stdout when we stop just in case we have any bytes
+        while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
+            if (out != NULL)
+                ::fwrite (stdio_buffer, 1, len, out);
+    }
+    
+    if (event_type & (Process::eBroadcastBitSTDERR | Process::eBroadcastBitStateChanged))
+    {
+        // Drain stderr when we stop just in case we have any bytes
+        while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
+            if (err != NULL)
+                ::fwrite (stdio_buffer, 1, len, err);
+    }
+    
+    if (event_type & Process::eBroadcastBitStateChanged)
+    {
+        StateType event_state = SBProcess::GetStateFromEvent (event);
+        
+        if (event_state == eStateInvalid)
+            return;
+        
+        bool is_stopped = StateIsStoppedState (event_state);
+        if (!is_stopped)
+            process.ReportEventState (event, out);
     }
 }
 
@@ -415,6 +351,7 @@
 ScriptLanguage
 SBDebugger::GetScriptingLanguage (const char *script_language_name)
 {
+
     return Args::StringToScriptLanguage (script_language_name,
                                          eScriptLanguageDefault,
                                          NULL);
@@ -582,7 +519,10 @@
 {
     SBTarget sb_target;
     if (m_opaque_sp)
+    {
+        // No need to lock, the target list is thread safe
         sb_target.reset(m_opaque_sp->GetTargetList().GetTargetAtIndex (idx));
+    }
     return sb_target;
 }
 
@@ -591,7 +531,10 @@
 {
     SBTarget sb_target;
     if (m_opaque_sp)
+    {
+        // No need to lock, the target list is thread safe
         sb_target.reset(m_opaque_sp->GetTargetList().FindTargetWithProcessID (pid));
+    }
     return sb_target;
 }
 
@@ -601,6 +544,7 @@
     SBTarget sb_target;
     if (m_opaque_sp && filename && filename[0])
     {
+        // No need to lock, the target list is thread safe
         ArchSpec arch;
         if (arch_name)
             arch.SetArch(arch_name);
@@ -615,7 +559,10 @@
 {
     SBTarget sb_target;
     if (m_opaque_sp)
+    {
+        // No need to lock, the target list is thread safe
         sb_target.reset(m_opaque_sp->GetTargetList().FindTargetWithProcess (process_sp.get()));
+    }
     return sb_target;
 }
 
@@ -624,7 +571,10 @@
 SBDebugger::GetNumTargets ()
 {
     if (m_opaque_sp)
+    {
+        // No need to lock, the target list is thread safe
         return m_opaque_sp->GetTargetList().GetNumTargets ();
+    }
     return 0;
 }
 
@@ -635,7 +585,10 @@
 
     SBTarget sb_target;
     if (m_opaque_sp)
+    {
+        // No need to lock, the target list is thread safe
         sb_target.reset(m_opaque_sp->GetTargetList().GetSelectedTarget ());
+    }
 
     if (log)
     {
@@ -685,6 +638,10 @@
 
     if (m_opaque_sp && reader.IsValid())
     {
+        TargetSP target_sp (m_opaque_sp->GetSelectedTarget());
+        Mutex::Locker api_locker;
+        if (target_sp)
+            api_locker.Reset(target_sp->GetAPIMutex().GetMutex());
         InputReaderSP reader_sp(*reader);
         m_opaque_sp->PushInputReader (reader_sp);
     }
@@ -713,6 +670,7 @@
 SBDebugger
 SBDebugger::FindDebuggerWithID (int id)
 {
+    // No need to lock, the debugger list is thread safe
     SBDebugger sb_debugger;
     lldb::DebuggerSP debugger_sp = Debugger::FindDebuggerWithID (id);
     if (debugger_sp)
@@ -816,19 +774,17 @@
 SBDebugger::SetScriptLanguage (lldb::ScriptLanguage script_lang)
 {
     if (m_opaque_sp)
+    {
         m_opaque_sp->SetScriptLanguage (script_lang);
+    }
 }
 
-
-
-
 bool
 SBDebugger::SetUseExternalEditor (bool value)
 {
     if (m_opaque_sp)
         return m_opaque_sp->SetUseExternalEditor (value);
-    else
-        return false;
+    return false;
 }
 
 bool
@@ -836,8 +792,7 @@
 {
     if (m_opaque_sp)
         return m_opaque_sp->GetUseExternalEditor ();
-    else
-        return false;
+    return false;
 }
 
 bool