/* Thread iterators and ranges for GDB, the GNU debugger.

   Copyright (C) 2018-2021 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include "defs.h"
#include "gdbthread.h"
#include "inferior.h"

/* See thread-iter.h.  */

all_threads_iterator::all_threads_iterator (begin_t)
{
  /* Advance M_INF/M_THR to the first thread's position.  */

  for (inferior &inf : inferior_list)
    {
      auto thr_iter = inf.thread_list.begin ();
      if (thr_iter != inf.thread_list.end ())
	{
	  m_inf = &inf;
	  m_thr = &*thr_iter;
	  return;
	}
    }
  m_inf = nullptr;
  m_thr = nullptr;
}

/* See thread-iter.h.  */

void
all_threads_iterator::advance ()
{
  intrusive_list<inferior>::iterator inf_iter (m_inf);
  intrusive_list<thread_info>::iterator thr_iter (m_thr);

  /* The loop below is written in the natural way as-if we'd always
     start at the beginning of the inferior list.  This fast forwards
     the algorithm to the actual current position.  */
  goto start;

  for (; inf_iter != inferior_list.end (); ++inf_iter)
    {
      m_inf = &*inf_iter;
      thr_iter = m_inf->thread_list.begin ();
      while (thr_iter != m_inf->thread_list.end ())
	{
	  m_thr = &*thr_iter;
	  return;
	start:
	  ++thr_iter;
	}
    }

  m_thr = nullptr;
}

/* See thread-iter.h.  */

bool
all_matching_threads_iterator::m_inf_matches ()
{
  return (m_filter_target == nullptr
	  || m_filter_target == m_inf->process_target ());
}

/* See thread-iter.h.  */

all_matching_threads_iterator::all_matching_threads_iterator
  (process_stratum_target *filter_target, ptid_t filter_ptid)
  : m_filter_target (filter_target)
{
  if (filter_ptid == minus_one_ptid)
    {
      /* Iterate on all threads of all inferiors, possibly filtering on
         FILTER_TARGET.  */
      m_mode = mode::ALL_THREADS;

      /* Seek the first thread of the first matching inferior.  */
      for (inferior &inf : inferior_list)
	{
	  m_inf = &inf;

	  if (!m_inf_matches ()
	      || inf.thread_list.empty ())
	    continue;

	  m_thr = &inf.thread_list.front ();
	  return;
	}
    }
  else
    {
      gdb_assert (filter_target != nullptr);

      if (filter_ptid.is_pid ())
	{
	  /* Iterate on all threads of the given inferior.  */
	  m_mode = mode::ALL_THREADS_OF_INFERIOR;

	  m_inf = find_inferior_pid (filter_target, filter_ptid.pid ());
	  if (m_inf != nullptr)
	    m_thr = &m_inf->thread_list.front ();
	}
      else
	{
	  /* Iterate on a single thread.  */
	  m_mode = mode::SINGLE_THREAD;

	  m_thr = find_thread_ptid (filter_target, filter_ptid);
	}
    }
}

/* See thread-iter.h.  */

void
all_matching_threads_iterator::advance ()
{
  switch (m_mode)
    {
    case mode::ALL_THREADS:
      {
	intrusive_list<inferior>::iterator inf_iter (m_inf);
	intrusive_list<thread_info>::iterator thr_iter
	  = m_inf->thread_list.iterator_to (*m_thr);

	/* The loop below is written in the natural way as-if we'd always
	   start at the beginning of the inferior list.  This fast forwards
	   the algorithm to the actual current position.  */
	goto start;

	for (; inf_iter != inferior_list.end (); ++inf_iter)
	  {
	    m_inf = &*inf_iter;

	    if (!m_inf_matches ())
	      continue;

	    thr_iter = m_inf->thread_list.begin ();
	    while (thr_iter != m_inf->thread_list.end ())
	      {
		m_thr = &*thr_iter;
		return;

	      start:
		++thr_iter;
	      }
	  }
      }
      m_thr = nullptr;
      break;

    case mode::ALL_THREADS_OF_INFERIOR:
      {
	intrusive_list<thread_info>::iterator thr_iter
	  = m_inf->thread_list.iterator_to (*m_thr);
	++thr_iter;
	if (thr_iter != m_inf->thread_list.end ())
	  m_thr = &*thr_iter;
	else
	  m_thr = nullptr;
	break;
      }

    case mode::SINGLE_THREAD:
      m_thr = nullptr;
      break;

    default:
      gdb_assert_not_reached ("invalid mode value");
    }
}
