/* Reference-counted smart pointer class

   Copyright (C) 2016-2018 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 GDB_REF_PTR_H
#define 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)
    : 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.  */
  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 /* GDB_REF_PTR_H */
