//===-- ThreadList.cpp ------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include <stdlib.h>

#include <algorithm>

#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadList.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.h"

using namespace lldb;
using namespace lldb_private;

ThreadList::ThreadList(Process *process)
    : ThreadCollection(), m_process(process), m_stop_id(0),
      m_selected_tid(LLDB_INVALID_THREAD_ID) {}

ThreadList::ThreadList(const ThreadList &rhs)
    : ThreadCollection(), m_process(rhs.m_process), m_stop_id(rhs.m_stop_id),
      m_selected_tid() {
  // Use the assignment operator since it uses the mutex
  *this = rhs;
}

const ThreadList &ThreadList::operator=(const ThreadList &rhs) {
  if (this != &rhs) {
    // Lock both mutexes to make sure neither side changes anyone on us while
    // the assignment occurs
    std::lock_guard<std::recursive_mutex> guard(GetMutex());
    std::lock_guard<std::recursive_mutex> rhs_guard(rhs.GetMutex());

    m_process = rhs.m_process;
    m_stop_id = rhs.m_stop_id;
    m_threads = rhs.m_threads;
    m_selected_tid = rhs.m_selected_tid;
  }
  return *this;
}

ThreadList::~ThreadList() {
  // Clear the thread list. Clear will take the mutex lock which will ensure
  // that if anyone is using the list they won't get it removed while using it.
  Clear();
}

lldb::ThreadSP ThreadList::GetExpressionExecutionThread() {
  if (m_expression_tid_stack.empty())
    return GetSelectedThread();
  ThreadSP expr_thread_sp = FindThreadByID(m_expression_tid_stack.back());
  if (expr_thread_sp)
    return expr_thread_sp;
  else
    return GetSelectedThread();
}

void ThreadList::PushExpressionExecutionThread(lldb::tid_t tid) {
  m_expression_tid_stack.push_back(tid);
}

void ThreadList::PopExpressionExecutionThread(lldb::tid_t tid) {
  assert(m_expression_tid_stack.back() == tid);
  m_expression_tid_stack.pop_back();
}

uint32_t ThreadList::GetStopID() const { return m_stop_id; }

void ThreadList::SetStopID(uint32_t stop_id) { m_stop_id = stop_id; }

uint32_t ThreadList::GetSize(bool can_update) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  if (can_update)
    m_process->UpdateThreadListIfNeeded();
  return m_threads.size();
}

ThreadSP ThreadList::GetThreadAtIndex(uint32_t idx, bool can_update) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  if (can_update)
    m_process->UpdateThreadListIfNeeded();

  ThreadSP thread_sp;
  if (idx < m_threads.size())
    thread_sp = m_threads[idx];
  return thread_sp;
}

ThreadSP ThreadList::FindThreadByID(lldb::tid_t tid, bool can_update) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  if (can_update)
    m_process->UpdateThreadListIfNeeded();

  ThreadSP thread_sp;
  uint32_t idx = 0;
  const uint32_t num_threads = m_threads.size();
  for (idx = 0; idx < num_threads; ++idx) {
    if (m_threads[idx]->GetID() == tid) {
      thread_sp = m_threads[idx];
      break;
    }
  }
  return thread_sp;
}

ThreadSP ThreadList::FindThreadByProtocolID(lldb::tid_t tid, bool can_update) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  if (can_update)
    m_process->UpdateThreadListIfNeeded();

  ThreadSP thread_sp;
  uint32_t idx = 0;
  const uint32_t num_threads = m_threads.size();
  for (idx = 0; idx < num_threads; ++idx) {
    if (m_threads[idx]->GetProtocolID() == tid) {
      thread_sp = m_threads[idx];
      break;
    }
  }
  return thread_sp;
}

ThreadSP ThreadList::RemoveThreadByID(lldb::tid_t tid, bool can_update) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  if (can_update)
    m_process->UpdateThreadListIfNeeded();

  ThreadSP thread_sp;
  uint32_t idx = 0;
  const uint32_t num_threads = m_threads.size();
  for (idx = 0; idx < num_threads; ++idx) {
    if (m_threads[idx]->GetID() == tid) {
      thread_sp = m_threads[idx];
      m_threads.erase(m_threads.begin() + idx);
      break;
    }
  }
  return thread_sp;
}

ThreadSP ThreadList::RemoveThreadByProtocolID(lldb::tid_t tid,
                                              bool can_update) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  if (can_update)
    m_process->UpdateThreadListIfNeeded();

  ThreadSP thread_sp;
  uint32_t idx = 0;
  const uint32_t num_threads = m_threads.size();
  for (idx = 0; idx < num_threads; ++idx) {
    if (m_threads[idx]->GetProtocolID() == tid) {
      thread_sp = m_threads[idx];
      m_threads.erase(m_threads.begin() + idx);
      break;
    }
  }
  return thread_sp;
}

ThreadSP ThreadList::GetThreadSPForThreadPtr(Thread *thread_ptr) {
  ThreadSP thread_sp;
  if (thread_ptr) {
    std::lock_guard<std::recursive_mutex> guard(GetMutex());

    uint32_t idx = 0;
    const uint32_t num_threads = m_threads.size();
    for (idx = 0; idx < num_threads; ++idx) {
      if (m_threads[idx].get() == thread_ptr) {
        thread_sp = m_threads[idx];
        break;
      }
    }
  }
  return thread_sp;
}

ThreadSP ThreadList::GetBackingThread(const ThreadSP &real_thread) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  ThreadSP thread_sp;
  const uint32_t num_threads = m_threads.size();
  for (uint32_t idx = 0; idx < num_threads; ++idx) {
    if (m_threads[idx]->GetBackingThread() == real_thread) {
      thread_sp = m_threads[idx];
      break;
    }
  }
  return thread_sp;
}

ThreadSP ThreadList::FindThreadByIndexID(uint32_t index_id, bool can_update) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  if (can_update)
    m_process->UpdateThreadListIfNeeded();

  ThreadSP thread_sp;
  const uint32_t num_threads = m_threads.size();
  for (uint32_t idx = 0; idx < num_threads; ++idx) {
    if (m_threads[idx]->GetIndexID() == index_id) {
      thread_sp = m_threads[idx];
      break;
    }
  }
  return thread_sp;
}

bool ThreadList::ShouldStop(Event *event_ptr) {
  // Running events should never stop, obviously...

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));

  // The ShouldStop method of the threads can do a whole lot of work, figuring
  // out whether the thread plan conditions are met.  So we don't want to keep
  // the ThreadList locked the whole time we are doing this.
  // FIXME: It is possible that running code could cause new threads
  // to be created.  If that happens, we will miss asking them whether they
  // should stop.  This is not a big deal since we haven't had a chance to hang
  // any interesting operations on those threads yet.

  collection threads_copy;
  {
    // Scope for locker
    std::lock_guard<std::recursive_mutex> guard(GetMutex());

    m_process->UpdateThreadListIfNeeded();
    for (lldb::ThreadSP thread_sp : m_threads) {
      // This is an optimization...  If we didn't let a thread run in between
      // the previous stop and this one, we shouldn't have to consult it for
      // ShouldStop.  So just leave it off the list we are going to inspect. On
      // Linux, if a thread-specific conditional breakpoint was hit, it won't
      // necessarily be the thread that hit the breakpoint itself that
      // evaluates the conditional expression, so the thread that hit the
      // breakpoint could still be asked to stop, even though it hasn't been
      // allowed to run since the previous stop.
      if (thread_sp->GetTemporaryResumeState() != eStateSuspended ||
          thread_sp->IsStillAtLastBreakpointHit())
        threads_copy.push_back(thread_sp);
    }

    // It is possible the threads we were allowing to run all exited and then
    // maybe the user interrupted or something, then fall back on looking at
    // all threads:

    if (threads_copy.size() == 0)
      threads_copy = m_threads;
  }

  collection::iterator pos, end = threads_copy.end();

  if (log) {
    log->PutCString("");
    log->Printf("ThreadList::%s: %" PRIu64 " threads, %" PRIu64
                " unsuspended threads",
                __FUNCTION__, (uint64_t)m_threads.size(),
                (uint64_t)threads_copy.size());
  }

  bool did_anybody_stop_for_a_reason = false;

  // If the event is an Interrupt event, then we're going to stop no matter
  // what.  Otherwise, presume we won't stop.
  bool should_stop = false;
  if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) {
    if (log)
      log->Printf(
          "ThreadList::%s handling interrupt event, should stop set to true",
          __FUNCTION__);

    should_stop = true;
  }

  // Now we run through all the threads and get their stop info's.  We want to
  // make sure to do this first before we start running the ShouldStop, because
  // one thread's ShouldStop could destroy information (like deleting a thread
  // specific breakpoint another thread had stopped at) which could lead us to
  // compute the StopInfo incorrectly. We don't need to use it here, we just
  // want to make sure it gets computed.

  for (pos = threads_copy.begin(); pos != end; ++pos) {
    ThreadSP thread_sp(*pos);
    thread_sp->GetStopInfo();
  }

  for (pos = threads_copy.begin(); pos != end; ++pos) {
    ThreadSP thread_sp(*pos);

    // We should never get a stop for which no thread had a stop reason, but
    // sometimes we do see this - for instance when we first connect to a
    // remote stub.  In that case we should stop, since we can't figure out the
    // right thing to do and stopping gives the user control over what to do in
    // this instance.
    //
    // Note, this causes a problem when you have a thread specific breakpoint,
    // and a bunch of threads hit the breakpoint, but not the thread which we
    // are waiting for.  All the threads that are not "supposed" to hit the
    // breakpoint are marked as having no stop reason, which is right, they
    // should not show a stop reason.  But that triggers this code and causes
    // us to stop seemingly for no reason.
    //
    // Since the only way we ever saw this error was on first attach, I'm only
    // going to trigger set did_anybody_stop_for_a_reason to true unless this
    // is the first stop.
    //
    // If this becomes a problem, we'll have to have another StopReason like
    // "StopInfoHidden" which will look invalid everywhere but at this check.

    if (thread_sp->GetProcess()->GetStopID() > 1)
      did_anybody_stop_for_a_reason = true;
    else
      did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason();

    const bool thread_should_stop = thread_sp->ShouldStop(event_ptr);
    if (thread_should_stop)
      should_stop |= true;
  }

  if (!should_stop && !did_anybody_stop_for_a_reason) {
    should_stop = true;
    if (log)
      log->Printf("ThreadList::%s we stopped but no threads had a stop reason, "
                  "overriding should_stop and stopping.",
                  __FUNCTION__);
  }

  if (log)
    log->Printf("ThreadList::%s overall should_stop = %i", __FUNCTION__,
                should_stop);

  if (should_stop) {
    for (pos = threads_copy.begin(); pos != end; ++pos) {
      ThreadSP thread_sp(*pos);
      thread_sp->WillStop();
    }
  }

  return should_stop;
}

Vote ThreadList::ShouldReportStop(Event *event_ptr) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  Vote result = eVoteNoOpinion;
  m_process->UpdateThreadListIfNeeded();
  collection::iterator pos, end = m_threads.end();

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));

  if (log)
    log->Printf("ThreadList::%s %" PRIu64 " threads", __FUNCTION__,
                (uint64_t)m_threads.size());

  // Run through the threads and ask whether we should report this event. For
  // stopping, a YES vote wins over everything.  A NO vote wins over NO
  // opinion.
  for (pos = m_threads.begin(); pos != end; ++pos) {
    ThreadSP thread_sp(*pos);
    const Vote vote = thread_sp->ShouldReportStop(event_ptr);
    switch (vote) {
    case eVoteNoOpinion:
      continue;

    case eVoteYes:
      result = eVoteYes;
      break;

    case eVoteNo:
      if (result == eVoteNoOpinion) {
        result = eVoteNo;
      } else {
        LLDB_LOG(log,
          "Thread {0:x} voted {1}, but lost out because result was {2}",
          thread_sp->GetID(), vote, result);
      }
      break;
    }
  }
  LLDB_LOG(log, "Returning {0}", result);
  return result;
}

void ThreadList::SetShouldReportStop(Vote vote) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  m_process->UpdateThreadListIfNeeded();
  collection::iterator pos, end = m_threads.end();
  for (pos = m_threads.begin(); pos != end; ++pos) {
    ThreadSP thread_sp(*pos);
    thread_sp->SetShouldReportStop(vote);
  }
}

Vote ThreadList::ShouldReportRun(Event *event_ptr) {

  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  Vote result = eVoteNoOpinion;
  m_process->UpdateThreadListIfNeeded();
  collection::iterator pos, end = m_threads.end();

  // Run through the threads and ask whether we should report this event. The
  // rule is NO vote wins over everything, a YES vote wins over no opinion.

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));

  for (pos = m_threads.begin(); pos != end; ++pos) {
    if ((*pos)->GetResumeState() != eStateSuspended) {
      switch ((*pos)->ShouldReportRun(event_ptr)) {
      case eVoteNoOpinion:
        continue;
      case eVoteYes:
        if (result == eVoteNoOpinion)
          result = eVoteYes;
        break;
      case eVoteNo:
        if (log)
          log->Printf("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64
                      ") says don't report.",
                      (*pos)->GetIndexID(), (*pos)->GetID());
        result = eVoteNo;
        break;
      }
    }
  }
  return result;
}

void ThreadList::Clear() {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  m_stop_id = 0;
  m_threads.clear();
  m_selected_tid = LLDB_INVALID_THREAD_ID;
}

void ThreadList::Destroy() {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  const uint32_t num_threads = m_threads.size();
  for (uint32_t idx = 0; idx < num_threads; ++idx) {
    m_threads[idx]->DestroyThread();
  }
}

void ThreadList::RefreshStateAfterStop() {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  m_process->UpdateThreadListIfNeeded();

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
  if (log && log->GetVerbose())
    log->Printf("Turning off notification of new threads while single stepping "
                "a thread.");

  collection::iterator pos, end = m_threads.end();
  for (pos = m_threads.begin(); pos != end; ++pos)
    (*pos)->RefreshStateAfterStop();
}

void ThreadList::DiscardThreadPlans() {
  // You don't need to update the thread list here, because only threads that
  // you currently know about have any thread plans.
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  collection::iterator pos, end = m_threads.end();
  for (pos = m_threads.begin(); pos != end; ++pos)
    (*pos)->DiscardThreadPlans(true);
}

bool ThreadList::WillResume() {
  // Run through the threads and perform their momentary actions. But we only
  // do this for threads that are running, user suspended threads stay where
  // they are.

  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  m_process->UpdateThreadListIfNeeded();

  collection::iterator pos, end = m_threads.end();

  // See if any thread wants to run stopping others.  If it does, then we won't
  // setup the other threads for resume, since they aren't going to get a
  // chance to run.  This is necessary because the SetupForResume might add
  // "StopOthers" plans which would then get to be part of the who-gets-to-run
  // negotiation, but they're coming in after the fact, and the threads that
  // are already set up should take priority.

  bool wants_solo_run = false;

  for (pos = m_threads.begin(); pos != end; ++pos) {
    lldbassert((*pos)->GetCurrentPlan() &&
               "thread should not have null thread plan");
    if ((*pos)->GetResumeState() != eStateSuspended &&
        (*pos)->GetCurrentPlan()->StopOthers()) {
      if ((*pos)->IsOperatingSystemPluginThread() &&
          !(*pos)->GetBackingThread())
        continue;
      wants_solo_run = true;
      break;
    }
  }

  if (wants_solo_run) {
    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
    if (log && log->GetVerbose())
      log->Printf("Turning on notification of new threads while single "
                  "stepping a thread.");
    m_process->StartNoticingNewThreads();
  } else {
    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
    if (log && log->GetVerbose())
      log->Printf("Turning off notification of new threads while single "
                  "stepping a thread.");
    m_process->StopNoticingNewThreads();
  }

  // Give all the threads that are likely to run a last chance to set up their
  // state before we negotiate who is actually going to get a chance to run...
  // Don't set to resume suspended threads, and if any thread wanted to stop
  // others, only call setup on the threads that request StopOthers...

  for (pos = m_threads.begin(); pos != end; ++pos) {
    if ((*pos)->GetResumeState() != eStateSuspended &&
        (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) {
      if ((*pos)->IsOperatingSystemPluginThread() &&
          !(*pos)->GetBackingThread())
        continue;
      (*pos)->SetupForResume();
    }
  }

  // Now go through the threads and see if any thread wants to run just itself.
  // if so then pick one and run it.

  ThreadList run_me_only_list(m_process);

  run_me_only_list.SetStopID(m_process->GetStopID());

  bool run_only_current_thread = false;

  for (pos = m_threads.begin(); pos != end; ++pos) {
    ThreadSP thread_sp(*pos);
    if (thread_sp->GetResumeState() != eStateSuspended &&
        thread_sp->GetCurrentPlan()->StopOthers()) {
      if ((*pos)->IsOperatingSystemPluginThread() &&
          !(*pos)->GetBackingThread())
        continue;

      // You can't say "stop others" and also want yourself to be suspended.
      assert(thread_sp->GetCurrentPlan()->RunState() != eStateSuspended);

      if (thread_sp == GetSelectedThread()) {
        // If the currently selected thread wants to run on its own, always let
        // it.
        run_only_current_thread = true;
        run_me_only_list.Clear();
        run_me_only_list.AddThread(thread_sp);
        break;
      }

      run_me_only_list.AddThread(thread_sp);
    }
  }

  bool need_to_resume = true;

  if (run_me_only_list.GetSize(false) == 0) {
    // Everybody runs as they wish:
    for (pos = m_threads.begin(); pos != end; ++pos) {
      ThreadSP thread_sp(*pos);
      StateType run_state;
      if (thread_sp->GetResumeState() != eStateSuspended)
        run_state = thread_sp->GetCurrentPlan()->RunState();
      else
        run_state = eStateSuspended;
      if (!thread_sp->ShouldResume(run_state))
        need_to_resume = false;
    }
  } else {
    ThreadSP thread_to_run;

    if (run_only_current_thread) {
      thread_to_run = GetSelectedThread();
    } else if (run_me_only_list.GetSize(false) == 1) {
      thread_to_run = run_me_only_list.GetThreadAtIndex(0);
    } else {
      int random_thread =
          (int)((run_me_only_list.GetSize(false) * (double)rand()) /
                (RAND_MAX + 1.0));
      thread_to_run = run_me_only_list.GetThreadAtIndex(random_thread);
    }

    for (pos = m_threads.begin(); pos != end; ++pos) {
      ThreadSP thread_sp(*pos);
      if (thread_sp == thread_to_run) {
        if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState()))
          need_to_resume = false;
      } else
        thread_sp->ShouldResume(eStateSuspended);
    }
  }

  return need_to_resume;
}

void ThreadList::DidResume() {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  collection::iterator pos, end = m_threads.end();
  for (pos = m_threads.begin(); pos != end; ++pos) {
    // Don't clear out threads that aren't going to get a chance to run, rather
    // leave their state for the next time around.
    ThreadSP thread_sp(*pos);
    if (thread_sp->GetResumeState() != eStateSuspended)
      thread_sp->DidResume();
  }
}

void ThreadList::DidStop() {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  collection::iterator pos, end = m_threads.end();
  for (pos = m_threads.begin(); pos != end; ++pos) {
    // Notify threads that the process just stopped. Note, this currently
    // assumes that all threads in the list stop when the process stops.  In
    // the future we will want to support a debugging model where some threads
    // continue to run while others are stopped.  We either need to handle that
    // somehow here or create a special thread list containing only threads
    // which will stop in the code that calls this method (currently
    // Process::SetPrivateState).
    ThreadSP thread_sp(*pos);
    if (StateIsRunningState(thread_sp->GetState()))
      thread_sp->DidStop();
  }
}

ThreadSP ThreadList::GetSelectedThread() {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  ThreadSP thread_sp = FindThreadByID(m_selected_tid);
  if (!thread_sp.get()) {
    if (m_threads.size() == 0)
      return thread_sp;
    m_selected_tid = m_threads[0]->GetID();
    thread_sp = m_threads[0];
  }
  return thread_sp;
}

bool ThreadList::SetSelectedThreadByID(lldb::tid_t tid, bool notify) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  ThreadSP selected_thread_sp(FindThreadByID(tid));
  if (selected_thread_sp) {
    m_selected_tid = tid;
    selected_thread_sp->SetDefaultFileAndLineToSelectedFrame();
  } else
    m_selected_tid = LLDB_INVALID_THREAD_ID;

  if (notify)
    NotifySelectedThreadChanged(m_selected_tid);

  return m_selected_tid != LLDB_INVALID_THREAD_ID;
}

bool ThreadList::SetSelectedThreadByIndexID(uint32_t index_id, bool notify) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  ThreadSP selected_thread_sp(FindThreadByIndexID(index_id));
  if (selected_thread_sp.get()) {
    m_selected_tid = selected_thread_sp->GetID();
    selected_thread_sp->SetDefaultFileAndLineToSelectedFrame();
  } else
    m_selected_tid = LLDB_INVALID_THREAD_ID;

  if (notify)
    NotifySelectedThreadChanged(m_selected_tid);

  return m_selected_tid != LLDB_INVALID_THREAD_ID;
}

void ThreadList::NotifySelectedThreadChanged(lldb::tid_t tid) {
  ThreadSP selected_thread_sp(FindThreadByID(tid));
  if (selected_thread_sp->EventTypeHasListeners(
          Thread::eBroadcastBitThreadSelected))
    selected_thread_sp->BroadcastEvent(
        Thread::eBroadcastBitThreadSelected,
        new Thread::ThreadEventData(selected_thread_sp));
}

void ThreadList::Update(ThreadList &rhs) {
  if (this != &rhs) {
    // Lock both mutexes to make sure neither side changes anyone on us while
    // the assignment occurs
    std::lock_guard<std::recursive_mutex> guard(GetMutex());

    m_process = rhs.m_process;
    m_stop_id = rhs.m_stop_id;
    m_threads.swap(rhs.m_threads);
    m_selected_tid = rhs.m_selected_tid;

    // Now we look for threads that we are done with and make sure to clear
    // them up as much as possible so anyone with a shared pointer will still
    // have a reference, but the thread won't be of much use. Using
    // std::weak_ptr for all backward references (such as a thread to a
    // process) will eventually solve this issue for us, but for now, we need
    // to work around the issue
    collection::iterator rhs_pos, rhs_end = rhs.m_threads.end();
    for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) {
      const lldb::tid_t tid = (*rhs_pos)->GetID();
      bool thread_is_alive = false;
      const uint32_t num_threads = m_threads.size();
      for (uint32_t idx = 0; idx < num_threads; ++idx) {
        ThreadSP backing_thread = m_threads[idx]->GetBackingThread();
        if (m_threads[idx]->GetID() == tid ||
            (backing_thread && backing_thread->GetID() == tid)) {
          thread_is_alive = true;
          break;
        }
      }
      if (!thread_is_alive)
        (*rhs_pos)->DestroyThread();
    }
  }
}

void ThreadList::Flush() {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  collection::iterator pos, end = m_threads.end();
  for (pos = m_threads.begin(); pos != end; ++pos)
    (*pos)->Flush();
}

std::recursive_mutex &ThreadList::GetMutex() const {
  return m_process->m_thread_mutex;
}

ThreadList::ExpressionExecutionThreadPusher::ExpressionExecutionThreadPusher(
    lldb::ThreadSP thread_sp)
    : m_thread_list(nullptr), m_tid(LLDB_INVALID_THREAD_ID) {
  if (thread_sp) {
    m_tid = thread_sp->GetID();
    m_thread_list = &thread_sp->GetProcess()->GetThreadList();
    m_thread_list->PushExpressionExecutionThread(m_tid);
  }
}
