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

#ifndef LIB_FIDL_LLCPP_TRACKING_PTR_H_
#define LIB_FIDL_LLCPP_TRACKING_PTR_H_

#include <lib/fidl/walker.h>

#include <cstddef>
#include <functional>
#include <memory>
#include <type_traits>

#include "aligned.h"
#include "array.h"
#include "unowned_ptr.h"

namespace fidl {

// tracking_ptr is a pointer that tracks ownership - it can either own or not own the pointed
// memory.
//
// When it owns memory, it acts similar to unique_ptr. When the pointer goes out of scope, the
// pointed object is deleted. tracking_ptr only supports move constructors like unique_ptr.
// When tracking_ptr points to unowned memory, no deletion occurs when tracking_ptr goes out
// of scope.
//
// This is implemented by reserving the least significant bit (LSB) of the pointer for use by
// tracking_ptr. For this to work, pointed objects must have at least 2-byte alignment so
// that the LSB of the pointer is 0. Heap allocated objects on modern systems are at least
// 4-byte aligned (32-bit) or 8-byte aligned (64-bit). An LSB of 0 means the pointed value
// is unowned. If the bit is 1, the pointed value is owned by tracking_ptr and will be freed
// when tracking_ptr is destructed.
//
// Arrays are special cased, similar to unique_ptr. tracking_ptr<int[]> does not act like a
// int[]* but rather it acts like a int* with features specific to arrays, such as indexing
// and deletion via the delete[] operator. The array specializations of tracking_ptr --
// e.g. tracking_ptr<int[]> -- has an internal memory layout that is a pointer + bool, so it
// is NOT the same width as a raw pointer.  The LSB is not used for ownership for arrays
// because it is common to read from a buffer starting at arbitrary offset.
//
// tracking_ptr<void> is also a special case and generally should only be used when it is
// necessary to store values in an untyped representation (for instance if a pointer can be
// one of a few types). tracking_ptr<void> can only be constructed with a non-null value
// from another tracking_ptr. It is an error to destruct a tracking_ptr<void> containing an
// owned pointer - it is expected that the pointer is moved out of the tracking_ptr first.
//
// Example:
// int i = 1;
// tracking_ptr<int> ptr = unowned_ptr_t<int>(&i); // Unowned pointer.
// ptr = std::make_unique<int>(2); // Owned pointer.
//
// tracking_ptr<int[]> array_ptr = std::make_unique<int[]>(2);
// array_ptr[1] = 5;
//
// Note: despite Fuchsia disabling exceptions, some methods are marked noexcept to allow
// for optimizations. For instance, vector has an optimization where it will move rather
// than copy if certain methods are marked with noexcept.
template <typename T>
class tracking_ptr final {
  template <typename>
  friend class tracking_ptr;

  // A marked_ptr is a pointer with the LSB reserved for the ownership bit.
  using marked_ptr = uintptr_t;
  static constexpr marked_ptr kOwnershipMask = internal::kNonArrayTrackingPtrOwnershipMask;
  static constexpr marked_ptr kNullMarkedPtr = 0x0;

  static constexpr size_t kMinAlignment = 2;
  static_assert(kOwnershipMask == 1, "alignment is dependent on ownership mask");

 public:
  constexpr tracking_ptr() noexcept { set_marked(kNullMarkedPtr); }
  constexpr tracking_ptr(std::nullptr_t) noexcept { set_marked(kNullMarkedPtr); }
  // Disabled constructor that exists to produce helpful error messages for the user.
  // Use templating to only trigger the static assert when the constructor is used.
  template <bool U = true, typename = std::enable_if_t<U>>
  tracking_ptr(T* raw_ptr) {
    static_assert(!U,
                  "fidl::tracking_ptr cannot be constructed directly from a raw pointer. "
                  "If tracking_ptr should not own the memory, indicate this by constructing a "
                  "fidl::unowned_ptr_t "
                  "using the fidl::unowned_ptr(&val) helper. "
                  "As an alternative, consider using a fidl::Allocator."
                  " For heap allocator values, construct with unique_ptr<T>.");
  }
  template <typename U>
  tracking_ptr(tracking_ptr<U>&& other) noexcept {
    // Force a static cast to restrict the types of assignments that can be made.
    // Ideally this would be implemented with a type trait, but none exist now.
    set_marked(reinterpret_cast<marked_ptr>(
        static_cast<T*>(reinterpret_cast<U*>(other.release_marked_ptr()))));
  }
  template <typename U = T, typename = std::enable_if_t<std::is_const<U>::value>>
  tracking_ptr(tracking_ptr<std::remove_const_t<U>>&& other) noexcept {
    // Force a static cast to restrict the types of assignments that can be made.
    // Ideally this would be implemented with a type trait, but none exist now.
    set_marked(reinterpret_cast<marked_ptr>(
        static_cast<T*>(reinterpret_cast<U*>(other.release_marked_ptr()))));
  }
  template <typename U = T, typename = std::enable_if_t<!std::is_void<U>::value>>
  tracking_ptr(std::unique_ptr<U>&& other) {
    set_owned(other.release());
  }
  tracking_ptr(unowned_ptr_t<T> other) {
    static_assert(std::alignment_of<T>::value >= kMinAlignment,
                  "unowned_ptr_t must point to an aligned value. "
                  "An insufficiently aligned value can be aligned with fidl::aligned");
    set_unowned(other.get());
  }
  template <typename U = T, typename = std::enable_if_t<std::is_const<U>::value>>
  tracking_ptr(unowned_ptr_t<std::remove_const_t<U>> other) {
    static_assert(std::alignment_of<T>::value >= kMinAlignment,
                  "unowned_ptr_t must point to an aligned value. "
                  "An insufficiently aligned value can be aligned with fidl::aligned");
    set_unowned(other.get());
  }
  // This constructor exists to strip off 'aligned' from the type (aligned<bool> -> bool).
  tracking_ptr(unowned_ptr_t<aligned<T>> other) { set_unowned(&other->value); }
  tracking_ptr(const tracking_ptr&) = delete;

  ~tracking_ptr() { reset_marked(kNullMarkedPtr); }

  tracking_ptr& operator=(tracking_ptr&& other) noexcept {
    reset_marked(other.release_marked_ptr());
    return *this;
  }
  tracking_ptr& operator=(const tracking_ptr&) = delete;

  template <typename U = T, typename = std::enable_if_t<!std::is_void<U>::value>>
  U& operator*() const {
    return *get();
  }
  template <typename U = T, typename = std::enable_if_t<!std::is_void<U>::value>>
  U* operator->() const noexcept {
    return get();
  }
  T* get() const noexcept { return reinterpret_cast<T*>(mptr_ & ~kOwnershipMask); }
  explicit operator bool() const noexcept { return get() != nullptr; }

 private:
  template <typename U, typename = void>
  struct Deleter {
    static void delete_ptr(U* ptr) { delete ptr; }
  };
  template <typename U>
  struct Deleter<U, std::enable_if_t<std::is_void<U>::value>> {
    static void delete_ptr(U*) {
      assert(false &&
             "Cannot delete void* in tracking_ptr<void>. "
             "First std::move contained value to appropriate typed pointer.");
    }
  };

  void reset_marked(marked_ptr new_ptr) {
    if (is_owned()) {
      Deleter<T>::delete_ptr(get());
    }
    set_marked(new_ptr);
  }
  bool is_owned() const noexcept { return (mptr_ & kOwnershipMask) != 0; }

  void set_marked(marked_ptr new_ptr) noexcept { mptr_ = new_ptr; }
  void set_unowned(T* new_ptr) {
    assert_lsb_not_set(new_ptr);
    set_marked(reinterpret_cast<marked_ptr>(new_ptr));
  }
  void set_owned(T* new_ptr) {
    assert_lsb_not_set(new_ptr);
    marked_ptr ptr_marked_owned = reinterpret_cast<marked_ptr>(new_ptr) | kOwnershipMask;
    set_marked(ptr_marked_owned);
  }
  static void assert_lsb_not_set(T* p) {
    if (reinterpret_cast<marked_ptr>(p) & kOwnershipMask) {
      abort();
    }
  }

  marked_ptr release_marked_ptr() noexcept {
    marked_ptr temp = mptr_;
    if (is_owned()) {
      // Unowned pointers keep their value like raw pointers, but owned pointers should zero.
      mptr_ = kNullMarkedPtr;
    }
    return temp;
  }

  marked_ptr mptr_;
};

template <typename T>
class tracking_ptr<T[]> final {
  template <typename>
  friend class tracking_ptr;

 public:
  constexpr tracking_ptr() noexcept {}
  constexpr tracking_ptr(std::nullptr_t) noexcept {}
  // Disabled constructor that exists to produce helpful error messages for the user.
  // Use templating to only trigger the static assert when the constructor is used.
  template <bool U = true, typename = std::enable_if_t<U>>
  tracking_ptr(T* raw_ptr) {
    static_assert(!U,
                  "fidl::tracking_ptr cannot be constructed directly from a raw pointer. "
                  "If tracking_ptr should not own the memory, indicate this by constructing a "
                  "fidl::unowned_ptr_t "
                  "using the fidl::unowned_ptr(&val) helper. "
                  "As an alternative, consider using a fidl::Allocator."
                  " For heap allocator values, construct with unique_ptr<T>.");
  }

  tracking_ptr(tracking_ptr&& other) noexcept {
    reset(other.is_owned_, other.ptr_);
    other.release();
  }
  template <typename U = T, typename = std::enable_if_t<std::is_const<U>::value>>
  tracking_ptr(tracking_ptr<std::remove_const_t<U>[]>&& other) noexcept {
    reset(other.is_owned_, other.ptr_);
    other.release();
  }
  template <typename U = T, typename = std::enable_if_t<!std::is_void<U>::value>>
  tracking_ptr(std::unique_ptr<U>&& other) {
    reset(true, other.release());
  }
  tracking_ptr(unowned_ptr_t<T> other) { reset(false, other.get()); }
  template <typename U = T, typename = std::enable_if_t<std::is_const<U>::value>>
  tracking_ptr(unowned_ptr_t<std::remove_const_t<U>> other) {
    reset(false, other.get());
  }
  tracking_ptr(const tracking_ptr&) = delete;

  ~tracking_ptr() { reset(false, nullptr); }

  tracking_ptr& operator=(tracking_ptr&& other) noexcept {
    reset(other.is_owned_, other.ptr_);
    other.release();
    return *this;
  }
  tracking_ptr& operator=(const tracking_ptr&) = delete;

  T& operator[](size_t index) const { return get()[index]; }
  T* get() const noexcept { return ptr_; }
  explicit operator bool() const noexcept { return get() != nullptr; }

  bool is_owned() { return is_owned_; }

  // Hand off responsibility of ownership to the caller.
  // The internal data can be retrieved through get() and is_owned() before calling release().
  void release() {
    if (is_owned()) {
      // Unowned pointers keep their value like raw pointers, but owned pointers should zero.
      ptr_ = nullptr;
      is_owned_ = false;
    }
  }

 private:
  void reset(bool is_owned, T* ptr) {
    if (is_owned_) {
      delete[] ptr_;
    }
    is_owned_ = is_owned;
    ptr_ = ptr;
  }

  T* ptr_ = nullptr;
  bool is_owned_ = false;
};

// Non-array tracking_ptr (and only non-array tracking_ptr) should match the layout of raw pointers.
static_assert(sizeof(fidl::tracking_ptr<void>) == sizeof(void*),
              "tracking_ptr must have the same size as a raw pointer");
static_assert(sizeof(fidl::tracking_ptr<uint8_t>) == sizeof(uint8_t*),
              "tracking_ptr must have the same size as a raw pointer");

// Array tracking_ptr is wider.
static_assert(sizeof(fidl::tracking_ptr<uint8_t[]>) >= sizeof(uint8_t*),
              "tracking_ptr for arrays is bigger than a raw pointer");

#define TRACKING_PTR_OPERATOR_COMPARISONS(func_name, op)                 \
  template <typename T, typename U>                                      \
  bool func_name(const tracking_ptr<T>& p1, const tracking_ptr<U>& p2) { \
    return p1.get() op p2.get();                                         \
  }
#define TRACKING_PTR_NULLPTR_COMPARISONS(func_name, op)                \
  template <typename T>                                                \
  bool func_name(const tracking_ptr<T>& p1, const std::nullptr_t p2) { \
    return p1.get() op nullptr;                                        \
  }                                                                    \
  template <typename T>                                                \
  bool func_name(const std::nullptr_t p1, const tracking_ptr<T>& p2) { \
    return nullptr op p2.get();                                        \
  }

TRACKING_PTR_OPERATOR_COMPARISONS(operator==, ==)
TRACKING_PTR_NULLPTR_COMPARISONS(operator==, ==)
TRACKING_PTR_OPERATOR_COMPARISONS(operator!=, !=)
TRACKING_PTR_NULLPTR_COMPARISONS(operator!=, !=)
TRACKING_PTR_OPERATOR_COMPARISONS(operator<, <)
TRACKING_PTR_OPERATOR_COMPARISONS(operator<=, <=)
TRACKING_PTR_OPERATOR_COMPARISONS(operator>, >)
TRACKING_PTR_OPERATOR_COMPARISONS(operator>=, >=)

}  // namespace fidl

namespace std {

template <typename T>
void swap(fidl::tracking_ptr<T>& lhs, fidl::tracking_ptr<T>& rhs) noexcept {
  auto temp = std::move(rhs);
  rhs = std::move(lhs);
  lhs = std::move(temp);
}

template <typename T>
struct hash<fidl::tracking_ptr<T>> {
  size_t operator()(const fidl::tracking_ptr<T>& ptr) const {
    return hash<typename std::remove_extent_t<T>*>{}(ptr.get());
  }
};

}  // namespace std

#endif  // LIB_FIDL_LLCPP_TRACKING_PTR_H_
