// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Provides a smart pointer class for intrusively reference-counted objects.

#ifndef FLUTTER_FML_MEMORY_REF_PTR_H_
#define FLUTTER_FML_MEMORY_REF_PTR_H_

#include <cstddef>
#include <functional>
#include <utility>

#include "flutter/fml/logging.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/memory/ref_ptr_internal.h"

namespace fml {

// A smart pointer class for intrusively reference-counted objects (e.g., those
// subclassing |RefCountedThreadSafe| -- see ref_counted.h).
//
// Such objects require *adoption* to obtain the first |RefPtr|, which is
// accomplished using |AdoptRef| (see below). (This is due to such objects being
// constructed with a reference count of 1. The adoption requirement is
// enforced, at least in Debug builds, by assertions.)
//
// E.g., if |Foo| is an intrusively reference-counted class:
//
//   // The |AdoptRef| may be put in a static factory method (e.g., if |Foo|'s
//   // constructor is private).
//   RefPtr<Foo> my_foo_ptr(AdoptRef(new Foo()));
//
//   // Now OK, since "my Foo" has been adopted ...
//   RefPtr<Foo> another_ptr_to_my_foo(my_foo_ptr.get());
//
//   // ... though this would preferable in this situation.
//   RefPtr<Foo> yet_another_ptr_to_my_foo(my_foo_ptr);
//
// Unlike Chromium's |scoped_refptr|, |RefPtr| is only explicitly constructible
// from a plain pointer (and not assignable). It is however implicitly
// constructible from |nullptr|. So:
//
//   RefPtr<Foo> foo(plain_ptr_to_adopted_foo);    // OK.
//   foo = plain_ptr_to_adopted_foo;               // Not OK (doesn't compile).
//   foo = RefPtr<Foo>(plain_ptr_to_adopted_foo);  // OK.
//   foo = nullptr;                                // OK.
//
// And if we have |void MyFunction(RefPtr<Foo> foo)|, calling it using
// |MyFunction(nullptr)| is also valid.
//
// Implementation note: For copy/move constructors/operator=s, we often have
// templated versions, so that the operation can be done on a |RefPtr<U>|, where
// |U| is a subclass of |T|. However, we also have non-templated versions with
// |U = T|, since the templated versions don't count as copy/move
// constructors/operator=s for the purposes of causing the default copy
// constructor/operator= to be deleted. E.g., if we didn't declare any
// non-templated versions, we'd get the default copy constructor/operator= (we'd
// only not get the default move constructor/operator= by virtue of having a
// destructor)! (In fact, it'd suffice to only declare a non-templated move
// constructor or move operator=, which would cause the copy
// constructor/operator= to be deleted, but for clarity we include explicit
// non-templated versions of everything.)
template <typename T>
class RefPtr final {
 public:
  RefPtr() : ptr_(nullptr) {}
  RefPtr(std::nullptr_t)
      : ptr_(nullptr) {}  // NOLINT(google-explicit-constructor)

  // Explicit constructor from a plain pointer (to an object that must have
  // already been adopted). (Note that in |T::T()|, references to |this| cannot
  // be taken, since the object being constructed will not have been adopted
  // yet.)
  template <typename U>
  explicit RefPtr(U* p) : ptr_(p) {
    if (ptr_) {
      ptr_->AddRef();
    }
  }

  // Copy constructor.
  RefPtr(const RefPtr<T>& r) : ptr_(r.ptr_) {
    if (ptr_) {
      ptr_->AddRef();
    }
  }

  template <typename U>
  RefPtr(const RefPtr<U>& r)
      : ptr_(r.ptr_) {  // NOLINT(google-explicit-constructor)
    if (ptr_) {
      ptr_->AddRef();
    }
  }

  // Move constructor.
  RefPtr(RefPtr<T>&& r) : ptr_(r.ptr_) { r.ptr_ = nullptr; }

  template <typename U>
  RefPtr(RefPtr<U>&& r) : ptr_(r.ptr_) {  // NOLINT(google-explicit-constructor)
    r.ptr_ = nullptr;
  }

  // Destructor.
  ~RefPtr() {
    if (ptr_) {
      ptr_->Release();
    }
  }

  T* get() const { return ptr_; }

  T& operator*() const {
    FML_DCHECK(ptr_);
    return *ptr_;
  }

  T* operator->() const {
    FML_DCHECK(ptr_);
    return ptr_;
  }

  // Copy assignment.
  RefPtr<T>& operator=(const RefPtr<T>& r) {
    // Handle self-assignment.
    if (r.ptr_ == ptr_) {
      return *this;
    }
    if (r.ptr_) {
      r.ptr_->AddRef();
    }
    T* old_ptr = ptr_;
    ptr_ = r.ptr_;
    if (old_ptr) {
      old_ptr->Release();
    }
    return *this;
  }

  template <typename U>
  RefPtr<T>& operator=(const RefPtr<U>& r) {
    if (reinterpret_cast<T*>(r.ptr_) == ptr_) {
      return *this;
    }
    if (r.ptr_) {
      r.ptr_->AddRef();
    }
    T* old_ptr = ptr_;
    ptr_ = r.ptr_;
    if (old_ptr) {
      old_ptr->Release();
    }
    return *this;
  }

  // Move assignment.
  // Note: Like |std::shared_ptr|, we support self-move and move assignment is
  // equivalent to |RefPtr<T>(std::move(r)).swap(*this)|.
  RefPtr<T>& operator=(RefPtr<T>&& r) {
    RefPtr<T>(std::move(r)).swap(*this);
    return *this;
  }

  template <typename U>
  RefPtr<T>& operator=(RefPtr<U>&& r) {
    RefPtr<T>(std::move(r)).swap(*this);
    return *this;
  }

  void swap(RefPtr<T>& r) {
    T* p = ptr_;
    ptr_ = r.ptr_;
    r.ptr_ = p;
  }

  // Returns a new |RefPtr<T>| with the same contents as this pointer. Useful
  // when a function takes a |RefPtr<T>&&| argument and the caller wants to
  // retain its reference (rather than moving it).
  RefPtr<T> Clone() const { return *this; }

  explicit operator bool() const { return !!ptr_; }

  template <typename U>
  bool operator==(const RefPtr<U>& rhs) const {
    return ptr_ == rhs.ptr_;
  }

  template <typename U>
  bool operator!=(const RefPtr<U>& rhs) const {
    return !operator==(rhs);
  }

  template <typename U>
  bool operator<(const RefPtr<U>& rhs) const {
    return ptr_ < rhs.ptr_;
  }

 private:
  template <typename U>
  friend class RefPtr;

  friend RefPtr<T> AdoptRef<T>(T*);

  enum AdoptTag { ADOPT };
  RefPtr(T* ptr, AdoptTag) : ptr_(ptr) { FML_DCHECK(ptr_); }

  T* ptr_;
};

// Adopts a newly-created |T|. Typically used in a static factory method, like:
//
//   // static
//   RefPtr<Foo> Foo::Create() {
//     return AdoptRef(new Foo());
//   }
template <typename T>
inline RefPtr<T> AdoptRef(T* ptr) {
#ifndef NDEBUG
  ptr->Adopt();
#endif
  return RefPtr<T>(ptr, RefPtr<T>::ADOPT);
}

// Constructs a |RefPtr<T>| from a plain pointer (to an object that must
// have already been adoped).  Avoids having to spell out the full type name.
//
//   Foo* foo = ...;
//   auto foo_ref = Ref(foo);
//
// (|foo_ref| will be of type |RefPtr<Foo>|.)
template <typename T>
inline RefPtr<T> Ref(T* ptr) {
  return RefPtr<T>(ptr);
}

// Creates an intrusively reference counted |T|, producing a |RefPtr<T>| (and
// performing the required adoption). Use like:
//
//   auto my_foo = MakeRefCounted<Foo>(ctor_arg1, ctor_arg2);
//
// (|my_foo| will be of type |RefPtr<Foo>|.)
template <typename T, typename... Args>
RefPtr<T> MakeRefCounted(Args&&... args) {
  return internal::MakeRefCountedHelper<T>::MakeRefCounted(
      std::forward<Args>(args)...);
}

}  // namespace fml

// Inject custom std::hash<> function object for |RefPtr<T>|.
namespace std {
template <typename T>
struct hash<fml::RefPtr<T>> {
  using argument_type = fml::RefPtr<T>;
  using result_type = std::size_t;

  result_type operator()(const argument_type& ptr) const {
    return std::hash<T*>()(ptr.get());
  }
};
}  // namespace std

#endif  // FLUTTER_FML_MEMORY_REF_PTR_H_
