/* Reference-counted smart pointer class

   Copyright (C) 2016-2025 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 GDBSUPPORT_GDB_REF_PTR_H
#define GDBSUPPORT_GDB_REF_PTR_H

#include <cstddef>

namespace gdb
{

/* An instance of this class either holds a reference to a
   reference-counted object or is "NULL".  Reference counting is
   handled externally by a policy class.  If the object holds a
   reference, then when the object is destroyed, the reference is
   decref'd.

   Normally an instance is constructed using a pointer.  This sort of
   initialization lets this class manage the lifetime of that
   reference.

   Assignment and copy construction will make a new reference as
   appropriate.  Assignment from a plain pointer is disallowed to
   avoid confusion about whether this acquires a new reference;
   instead use the "reset" method -- which, like the pointer
   constructor, transfers ownership.

   The policy class must provide two static methods:
   void incref (T *);
   void decref (T *);
*/
template<typename T, typename Policy>
class ref_ptr
{
 public:

  /* Create a new NULL instance.  */
  ref_ptr ()
    : m_obj (NULL)
  {
  }

  /* Create a new NULL instance.  Note that this is not explicit.  */
  ref_ptr (const std::nullptr_t)
    : m_obj (NULL)
  {
  }

  /* Create a new instance.  OBJ is a reference, management of which
     is now transferred to this class.  */
  explicit ref_ptr (T *obj)
    : m_obj (obj)
  {
  }

  /* Copy another instance.  */
  ref_ptr (const ref_ptr &other)
    : m_obj (other.m_obj)
  {
    if (m_obj != NULL)
      Policy::incref (m_obj);
  }

  /* Transfer ownership from OTHER.  */
  ref_ptr (ref_ptr &&other) noexcept
    : m_obj (other.m_obj)
  {
    other.m_obj = NULL;
  }

  /* Destroy this instance.  */
  ~ref_ptr ()
  {
    if (m_obj != NULL)
      Policy::decref (m_obj);
  }

  /* Copy another instance.  */
  ref_ptr &operator= (const ref_ptr &other)
  {
    /* Do nothing on self-assignment.  */
    if (this != &other)
      {
	reset (other.m_obj);
	if (m_obj != NULL)
	  Policy::incref (m_obj);
      }
    return *this;
  }

  /* Transfer ownership from OTHER.  */
  ref_ptr &operator= (ref_ptr &&other)
  {
    /* Do nothing on self-assignment.  */
    if (this != &other)
      {
	reset (other.m_obj);
	other.m_obj = NULL;
      }
    return *this;
  }

  /* Change this instance's referent.  OBJ is a reference, management
     of which is now transferred to this class.  */
  void reset (T *obj)
  {
    if (m_obj != NULL)
      Policy::decref (m_obj);
    m_obj = obj;
  }

  /* Return this instance's referent without changing the state of
     this class.  */
  T *get () const
  {
    return m_obj;
  }

  /* Return this instance's referent, and stop managing this
     reference.  The caller is now responsible for the ownership of
     the reference.  */
  ATTRIBUTE_UNUSED_RESULT T *release ()
  {
    T *result = m_obj;

    m_obj = NULL;
    return result;
  }

  /* Let users refer to members of the underlying pointer.  */
  T *operator-> () const
  {
    return m_obj;
  }

  /* Acquire a new reference and return a ref_ptr that owns it.  */
  static ref_ptr<T, Policy> new_reference (T *obj)
  {
    Policy::incref (obj);
    return ref_ptr<T, Policy> (obj);
  }

 private:

  T *m_obj;
};

template<typename T, typename Policy>
inline bool operator== (const ref_ptr<T, Policy> &lhs,
			const ref_ptr<T, Policy> &rhs)
{
  return lhs.get () == rhs.get ();
}

template<typename T, typename Policy>
inline bool operator== (const ref_ptr<T, Policy> &lhs, const T *rhs)
{
  return lhs.get () == rhs;
}

template<typename T, typename Policy>
inline bool operator== (const ref_ptr<T, Policy> &lhs, const std::nullptr_t)
{
  return lhs.get () == nullptr;
}

template<typename T, typename Policy>
inline bool operator== (const T *lhs, const ref_ptr<T, Policy> &rhs)
{
  return lhs == rhs.get ();
}

template<typename T, typename Policy>
inline bool operator== (const std::nullptr_t, const ref_ptr<T, Policy> &rhs)
{
  return nullptr == rhs.get ();
}

template<typename T, typename Policy>
inline bool operator!= (const ref_ptr<T, Policy> &lhs,
			const ref_ptr<T, Policy> &rhs)
{
  return lhs.get () != rhs.get ();
}

template<typename T, typename Policy>
inline bool operator!= (const ref_ptr<T, Policy> &lhs, const T *rhs)
{
  return lhs.get () != rhs;
}

template<typename T, typename Policy>
inline bool operator!= (const ref_ptr<T, Policy> &lhs, const std::nullptr_t)
{
  return lhs.get () != nullptr;
}

template<typename T, typename Policy>
inline bool operator!= (const T *lhs, const ref_ptr<T, Policy> &rhs)
{
  return lhs != rhs.get ();
}

template<typename T, typename Policy>
inline bool operator!= (const std::nullptr_t, const ref_ptr<T, Policy> &rhs)
{
  return nullptr != rhs.get ();
}

}

#endif /* GDBSUPPORT_GDB_REF_PTR_H */
