/* The ptid_t type and common functions operating on it.

   Copyright (C) 1986-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/>.  */

#ifndef COMMON_PTID_H
#define COMMON_PTID_H

/* The ptid struct is a collection of the various "ids" necessary for
   identifying the inferior process/thread being debugged.  This
   consists of the process id (pid), lightweight process id (lwp) and
   thread id (tid).  When manipulating ptids, the constructors,
   accessors, and predicates declared in this file should be used.  Do
   NOT access the struct ptid members directly.

   process_stratum targets that handle threading themselves should
   prefer using the ptid.lwp field, leaving the ptid.tid field for any
   thread_stratum target that might want to sit on top.
*/

#include <functional>
#include <string>

class ptid_t
{
public:
  /* Must have a trivial defaulted default constructor so that the
     type remains POD.  */
  ptid_t () noexcept = default;

  /* Make a ptid given the necessary PID, LWP, and TID components.

     A ptid with only a PID (LWP and TID equal to zero) is usually used to
     represent a whole process, including all its lwps/threads.  */

  explicit constexpr ptid_t (int pid, long lwp = 0, long tid = 0)
    : m_pid (pid), m_lwp (lwp), m_tid (tid)
  {}

  /* Fetch the pid (process id) component from the ptid.  */

  constexpr int pid () const
  { return m_pid; }

  /* Return true if the ptid's lwp member is non-zero.  */

  constexpr bool lwp_p () const
  { return m_lwp != 0; }

  /* Fetch the lwp (lightweight process) component from the ptid.  */

  constexpr long lwp () const
  { return m_lwp; }

  /* Return true if the ptid's tid member is non-zero.  */

  constexpr bool tid_p () const
  { return m_tid != 0; }

  /* Fetch the tid (thread id) component from a ptid.  */

  constexpr long tid () const
  { return m_tid; }

  /* Return true if the ptid represents a whole process, including all its
     lwps/threads.  Such ptids have the form of (pid, 0, 0), with
     pid != -1.  */

  constexpr bool is_pid () const
  {
    return (*this != make_null ()
	    && *this != make_minus_one ()
	    && m_lwp == 0
	    && m_tid == 0);
  }

  /* Compare two ptids to see if they are equal.  */

  constexpr bool operator== (const ptid_t &other) const
  {
    return (m_pid == other.m_pid
	    && m_lwp == other.m_lwp
	    && m_tid == other.m_tid);
  }

  /* Compare two ptids to see if they are different.  */

  constexpr bool operator!= (const ptid_t &other) const
  {
    return !(*this == other);
  }

  /* Return true if the ptid matches FILTER.  FILTER can be the wild
     card MINUS_ONE_PTID (all ptids match it); can be a ptid representing
     a process (ptid.is_pid () returns true), in which case, all lwps and
     threads of that given process match, lwps and threads of other
     processes do not; or, it can represent a specific thread, in which
     case, only that thread will match true.  The ptid must represent a
     specific LWP or THREAD, it can never be a wild card.  */

  constexpr bool matches (const ptid_t &filter) const
  {
    return (/* If filter represents any ptid, it's always a match.  */
	    filter == make_minus_one ()
	    /* If filter is only a pid, any ptid with that pid
	       matches.  */
	    || (filter.is_pid () && m_pid == filter.pid ())

	    /* Otherwise, this ptid only matches if it's exactly equal
	       to filter.  */
	    || *this == filter);
  }

  /* Return a string representation of the ptid.

     This is only meant to be used in debug messages.  */

  std::string to_string () const;

  /* Make a null ptid.  */

  static constexpr ptid_t make_null ()
  { return ptid_t (0, 0, 0); }

  /* Make a minus one ptid.  */

  static constexpr ptid_t make_minus_one ()
  { return ptid_t (-1, 0, 0); }

private:
  /* Process id.  */
  int m_pid;

  /* Lightweight process id.  */
  long m_lwp;

  /* Thread id.  */
  long m_tid;
};

/* Functor to hash a ptid.  */

struct hash_ptid
{
  size_t operator() (const ptid_t &ptid) const
  {
    std::hash<long> long_hash;

    return (long_hash (ptid.pid ())
	    + long_hash (ptid.lwp ())
	    + long_hash (ptid.tid ()));
  }
};

/* The null or zero ptid, often used to indicate no process. */

extern const ptid_t null_ptid;

/* The (-1,0,0) ptid, often used to indicate either an error condition
   or a "don't care" condition, i.e, "run all threads."  */

extern const ptid_t minus_one_ptid;

#endif /* COMMON_PTID_H */
