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

// C Includes
#include <stdlib.h>

// C++ Includes
#include <algorithm>

// Other libraries and framework includes
// Project includes
#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
#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/ConvertEnum.h"
#include "lldb/Utility/LLDBAssert.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::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 {
        if (log)
          log->Printf("ThreadList::%s thread 0x%4.4" PRIx64
                      ": voted %s, but lost out because result was %s",
                      __FUNCTION__, thread_sp->GetID(), GetVoteAsCString(vote),
                      GetVoteAsCString(result));
      }
      break;
    }
  }
  if (log)
    log->Printf("ThreadList::%s returning %s", __FUNCTION__,
                GetVoteAsCString(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);
  }
}
