// Copyright 2016 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 FBL_INTRUSIVE_DOUBLE_LIST_H_
#define FBL_INTRUSIVE_DOUBLE_LIST_H_

#include <zircon/assert.h>

#include <utility>

#include <fbl/algorithm.h>
#include <fbl/intrusive_container_node_utils.h>
#include <fbl/intrusive_container_utils.h>
#include <fbl/intrusive_pointer_traits.h>

// Usage and Implementation Notes:
//
// fbl::DoublyLinkedList<> is a templated intrusive container class which
// allows users to manage doubly linked lists of objects.
//
// fbl::DoublyLinkedList<> follows the same patterns as
// fbl::SinglyLinkedList<> and implements a superset of the functionality
// (including support for managed pointer types).  Please refer to the "Usage
// Notes" section of fbl/intrusive_single_list.h for details.
//
// Additional functionality provided by a DoublyLinkedList<> includes...
// ++ O(1) push_back/pop_back/back (in addition to push_front/pop_front/front)
// ++ The ability to "insert" in addition to "insert_after"
// ++ The ability to "erase" in addition to "erase_next"
// ++ Support for bidirectional iteration.
//
// Under the hood, the state of a DoublyLinkedList<> contains a single raw
// pointer to the object which is the head of the list, or nullptr if the list
// is empty.  Each object on the list has a DoublyLinkedListNodeState<> which
// contains one raw pointer (prev) and one managed pointer (next) which are
// arranged in a ring.  The tail of a non-empty list can be found in O(1) time
// by following the prev pointer of the head node of the list.
namespace fbl {

// Fwd decl of sanity checker class used by tests.
namespace tests {
namespace intrusive_containers {
class DoublyLinkedListChecker;
template <typename>
class SequenceContainerTestEnvironment;
}  // namespace intrusive_containers
}  // namespace tests

// fwd decl of the list base class.
namespace internal {
template <typename PtrType>
class DoublyLinkedListBase;
}

template <typename PtrType_, NodeOptions Options = NodeOptions::None>
struct DoublyLinkedListNodeState
    : public internal::CommonNodeStateBase<DoublyLinkedListNodeState<PtrType_, Options>> {
 private:
  using Base = internal::CommonNodeStateBase<DoublyLinkedListNodeState<PtrType_, Options>>;

 public:
  using PtrType = PtrType_;
  using PtrTraits = internal::ContainerPtrTraits<PtrType>;
  static constexpr NodeOptions kNodeOptions = Options;

  constexpr DoublyLinkedListNodeState() {}
  ~DoublyLinkedListNodeState() {
    ZX_DEBUG_ASSERT(IsValid());
    if constexpr (!(kNodeOptions & fbl::NodeOptions::AllowClearUnsafe)) {
      ZX_DEBUG_ASSERT(!InContainer());
    }
  }

  bool IsValid() const { return ((next_ == nullptr) == (prev_ == nullptr)); }
  bool InContainer() const { return (next_ != nullptr); }

  template <typename NodeTraits>
  PtrType_ RemoveFromContainer() {
    static_assert(kNodeOptions & NodeOptions::AllowRemoveFromContainer,
                  "Node does not support direct RemoveFromContainer operations");

    return internal::DoublyLinkedListBase<PtrType_>::template internal_erase<NodeTraits>(*this);
  }

  // Defer to CommonNodeStateBase for enforcement of the various copy/move
  // rules.  Make sure, however, that we explicitly do not allow our own default
  // construction/assignment operators change anything about our state.
  DoublyLinkedListNodeState(const DoublyLinkedListNodeState& other) : Base(other) {}
  DoublyLinkedListNodeState& operator=(const DoublyLinkedListNodeState& other) {
    this->Base::operator=(other);
    return *this;
  }
  DoublyLinkedListNodeState(DoublyLinkedListNodeState&& other) : Base(std::move(other)) {}
  DoublyLinkedListNodeState& operator=(DoublyLinkedListNodeState&& other) {
    this->Base::operator=(std::move(other));
    return *this;
  }

 private:
  template <typename, typename, SizeOrder, typename>
  friend class DoublyLinkedList;
  template <typename>
  friend class internal::DoublyLinkedListBase;
  template <typename>
  friend class tests::intrusive_containers::SequenceContainerTestEnvironment;
  friend class tests::intrusive_containers::DoublyLinkedListChecker;

  typename PtrTraits::RawPtrType next_ = nullptr;
  typename PtrTraits::RawPtrType prev_ = nullptr;
};

template <typename PtrType, NodeOptions Options, typename TagType>
struct DoublyLinkedListable;

template <typename PtrType_, typename TagType_>
struct DefaultDoublyLinkedListTraits {
 private:
  using ValueType = typename internal::ContainerPtrTraits<PtrType_>::ValueType;

 public:
  using PtrType = PtrType_;
  using TagType = TagType_;
  using PtrTraits = internal::ContainerPtrTraits<PtrType>;

  static auto& node_state(typename PtrTraits::RefType obj) {
    if constexpr (std::is_same_v<TagType, DefaultObjectTag>) {
      return obj.ValueType::dll_node_state_;
    } else {
      return obj.template GetContainableByTag<TagType>().dll_node_state_;
    }
  }

  using NodeState =
      std::decay_t<std::invoke_result_t<decltype(node_state), typename PtrTraits::RefType>>;
};

template <typename PtrType_, NodeOptions Options = NodeOptions::None,
          typename TagType_ = DefaultObjectTag>
struct DoublyLinkedListable {
 public:
  using PtrType = PtrType_;
  using TagType = TagType_;
  static constexpr NodeOptions kNodeOptions = Options;

  bool InContainer() const {
    using Node = DoublyLinkedListable<PtrType, Options, TagType>;
    return Node::dll_node_state_.InContainer();
  }

  PtrType RemoveFromContainer() {
    using ListTraits = DefaultDoublyLinkedListTraits<PtrType, TagType_>;
    return dll_node_state_.template RemoveFromContainer<ListTraits>();
  }

 private:
  friend struct DefaultDoublyLinkedListTraits<PtrType, TagType>;
  DoublyLinkedListNodeState<PtrType, Options> dll_node_state_;
};

namespace internal {

template <typename PtrType_>
class DoublyLinkedListBase {
 public:
  constexpr DoublyLinkedListBase() = default;
  ~DoublyLinkedListBase() {}

  using PtrType = PtrType_;
  using PtrTraits = internal::ContainerPtrTraits<PtrType>;
  using RawPtrType = typename PtrTraits::RawPtrType;

 protected:
  template <typename, NodeOptions>
  friend struct ::fbl::DoublyLinkedListNodeState;

  template <typename NodeTraits, typename NodeStateType>
  static PtrType internal_erase(NodeStateType& node_ns) {
    // No one should be calling internal erase with an invalid node state, or a
    // node state which is not in-container.
    ZX_DEBUG_ASSERT(node_ns.IsValid() && node_ns.InContainer());

    // Fetch the previous node's node state (this may be our own in the case
    // that we are the only element on the list)
    auto& prev_node_ns = NodeTraits::node_state(*node_ns.prev_);

    // Find the prev pointer we need to update.  If we are removing the tail
    // of the list, the prev pointer is head_'s prev pointer.  Otherwise, it
    // is the prev pointer of the node which currently follows "next_"
    auto& tgt_prev = internal::is_sentinel_ptr(node_ns.next_)
                         ? NodeTraits::node_state(*head_from_sentinel(node_ns.next_)).prev_
                         : NodeTraits::node_state(*node_ns.next_).prev_;

    // Find the next pointer we need to update.  If the next_ pointer of the
    // previous node state is a sentinel, removing the head of the list and the
    // next_ pointer we need to update is actually the head_ for the list.
    // Otherwise, it is simply the next_ pointer of the previous node state.
    auto& tgt_next = internal::is_sentinel_ptr(prev_node_ns.next_)
                         ? head_from_sentinel(prev_node_ns.next_)
                         : prev_node_ns.next_;

    RawPtrType erased = tgt_next;

    tgt_prev = node_ns.prev_;
    tgt_next = node_ns.next_;
    node_ns.prev_ = nullptr;
    node_ns.next_ = nullptr;

    return PtrTraits::Reclaim(erased);
  }

  constexpr RawPtrType sentinel() const { return internal::make_sentinel<RawPtrType>(this); }

  // State consists of a raw pointer to the head of the list.  Initially, this
  // is set to the special sentinel value, which allows iterators set to
  // this->end() to back up to the tail of the list.
  RawPtrType head_ = sentinel();

 private:
  // Fetch a reference to the head_ member the list referenced by a sentinel
  // value.
  static RawPtrType& head_from_sentinel(RawPtrType node) {
    return internal::unmake_sentinel<DoublyLinkedListBase<PtrType_>*>(node)->head_;
  }
};

}  // namespace internal

template <typename PtrType_, typename TagType_ = DefaultObjectTag,
          SizeOrder ListSizeOrder_ = SizeOrder::N,
          typename NodeTraits_ = DefaultDoublyLinkedListTraits<PtrType_, TagType_>>
class __POINTER(PtrType_) DoublyLinkedList : public internal::DoublyLinkedListBase<PtrType_>,
                                             private internal::SizeTracker<ListSizeOrder_> {
 private:
  using Base = internal::DoublyLinkedListBase<PtrType_>;

  // Private fwd decls of the iterator implementation.
  template <typename IterTraits>
  class iterator_impl;
  struct iterator_traits;
  struct const_iterator_traits;

 public:
  // Aliases used to reduce verbosity and expose types/traits to tests
  static constexpr SizeOrder ListSizeOrder = ListSizeOrder_;
  using typename Base::PtrType;
  using TagType = TagType_;
  using NodeTraits = NodeTraits_;

  using typename Base::PtrTraits;
  using typename Base::RawPtrType;
  using ValueType = typename PtrTraits::ValueType;
  using RefType = typename PtrTraits::RefType;
  using CheckerType = ::fbl::tests::intrusive_containers::DoublyLinkedListChecker;
  using ContainerType = DoublyLinkedList<PtrType_, TagType_, ListSizeOrder_, NodeTraits_>;

  // Declarations of the standard iterator types.
  using iterator = iterator_impl<iterator_traits>;
  using const_iterator = iterator_impl<const_iterator_traits>;

  // Doubly linked lists support constant order erase (erase using an iterator
  // or direct object reference).
  static constexpr bool SupportsConstantOrderErase = true;
  static constexpr bool SupportsConstantOrderSize = (ListSizeOrder == SizeOrder::Constant);
  static constexpr bool IsAssociative = false;
  static constexpr bool IsSequenced = true;

  // Default construction gives an empty list.
  constexpr DoublyLinkedList() noexcept {
    using NodeState = internal::node_state_t<NodeTraits, RefType>;

    // Make certain that the type of pointer we are expected to manage matches
    // the type of pointer that our Node type expects to manage.
    static_assert(std::is_same_v<PtrType, typename NodeState::PtrType>,
                  "DoublyLinkedList's pointer type must match its Node's pointer type");

    // Direct remove-from-container is only allowed if this list does not keep
    // track of it's size.
    static_assert((ListSizeOrder == SizeOrder::N) ||
                      !(NodeState::kNodeOptions & NodeOptions::AllowRemoveFromContainer),
                  "Nodes which allow RemoveFromContainer may not be used with DoublyLinkedLists "
                  "that track size");
  }

  // Rvalue construction is permitted, but will result in the move of the list
  // contents from one instance of the list to the other (even for unmanaged
  // pointers)
  DoublyLinkedList(DoublyLinkedList&& other_list) noexcept : DoublyLinkedList() {
    swap(other_list);
  }

  // Rvalue assignment is permitted for managed lists, and when the target is
  // an empty list of unmanaged pointers.  Like Rvalue construction, it will
  // result in the move of the source contents to the destination.
  DoublyLinkedList& operator=(DoublyLinkedList&& other_list) {
    ZX_DEBUG_ASSERT(PtrTraits::IsManaged || is_empty());

    clear();
    swap(other_list);

    return *this;
  }

  ~DoublyLinkedList() {
    // It is considered an error to allow a list of unmanaged pointers to
    // destruct if there are still elements in it.  Managed pointer lists
    // will automatically release their references to their elements.
    if (PtrTraits::IsManaged == false) {
      ZX_DEBUG_ASSERT(is_empty());
      if constexpr (SupportsConstantOrderSize) {
        ZX_DEBUG_ASSERT(this->SizeTrackerCount() == 0);
      }
    } else {
      clear();
    }
  }

  // Standard begin/end, cbegin/cend iterator accessors.
  iterator begin() { return iterator(head_); }
  const_iterator begin() const { return const_iterator(head_); }
  const_iterator cbegin() const { return const_iterator(head_); }

  iterator end() { return iterator(sentinel()); }
  const_iterator end() const { return const_iterator(sentinel()); }
  const_iterator cend() const { return const_iterator(sentinel()); }

  // make_iterator : construct an iterator out of a pointer to an object
  iterator make_iterator(ValueType& obj) { return iterator(&obj); }
  const_iterator make_iterator(const ValueType& obj) const {
    return const_iterator(&const_cast<ValueType&>(obj));
  }

  // is_empty : False if the list has at least one element in it, true otherwise.
  bool is_empty() const {
    ZX_DEBUG_ASSERT(head_ != nullptr);
    return internal::is_sentinel_ptr(head_);
  }

  // front
  //
  // Return a reference to the element at the front of the list without
  // removing it.  It is an error to call front on an empty list.
  typename PtrTraits::RefType front() {
    ZX_DEBUG_ASSERT(!is_empty());
    return *head_;
  }
  typename PtrTraits::ConstRefType front() const {
    ZX_DEBUG_ASSERT(!is_empty());
    return *head_;
  }

  // back
  //
  // Return a reference to the element at the back of the list without
  // removing it.  It is an error to call back on an empty list.
  typename PtrTraits::RefType back() {
    ZX_DEBUG_ASSERT(!is_empty());
    return *(NodeTraits::node_state(*head_).prev_);
  }

  typename PtrTraits::ConstRefType back() const {
    ZX_DEBUG_ASSERT(!is_empty());
    return *(NodeTraits::node_state(*head_).prev_);
  }

  // push_front : Push an element onto the front of the list.
  void push_front(const PtrType& ptr) { push_front(PtrType(ptr)); }
  void push_front(PtrType&& ptr) { internal_insert(head_, std::move(ptr)); }

  // push_back : Push an element onto the end of the list.
  void push_back(const PtrType& ptr) { push_back(PtrType(ptr)); }
  void push_back(PtrType&& ptr) { internal_insert(sentinel(), std::move(ptr)); }

  // insert : Insert an element before iter in the list, and return an
  // element to the newly-inserted element.
  iterator insert(const iterator& iter, const PtrType& ptr) { return insert(iter, PtrType(ptr)); }
  iterator insert(const iterator& iter, PtrType&& ptr) {
    return internal_insert(iter.node_, std::move(ptr));
  }

  iterator insert(ValueType& before, const PtrType& ptr) { return insert(before, PtrType(ptr)); }
  iterator insert(ValueType& before, PtrType&& ptr) {
    return internal_insert(&before, std::move(ptr));
  }

  // splice : Splice another list before iter in this list.
  void splice(const iterator& iter, DoublyLinkedList& other_list) {
    auto before = iter.node_;
    ZX_DEBUG_ASSERT(before != nullptr);
    ZX_DEBUG_ASSERT(head_ != nullptr);

    if (other_list.is_empty()) {
      return;
    }
    if (is_empty()) {
      ZX_DEBUG_ASSERT(before == sentinel());
      ZX_DEBUG_ASSERT(before == head_);
      swap(other_list);
      return;
    }

    // If we are being inserted before the sentinel, the we are the new
    // tail, and the node_state which contains the prev pointer we need to
    // update is head's.  Otherwise, it is the node_state of the node we are
    // being inserted before.
    auto& prev_ns = NodeTraits::node_state(internal::is_sentinel_ptr(before) ? *head_ : *before);
    auto& tgt_prev = prev_ns.prev_;

    // If we are being inserted before the head, then we need to update the
    // head pointer.  Otherwise, we need to update the next pointer of the
    // node which is about to come before us.
    auto& tgt_next = (head_ == before)                   ? head_
                     : internal::is_sentinel_ptr(before) ? NodeTraits::node_state(*tail()).next_
                                                         : NodeTraits::node_state(*tgt_prev).next_;

    auto& other_head_ns = NodeTraits::node_state(*other_list.head_);
    auto other_tail = other_list.tail();
    auto& other_tail_ns = NodeTraits::node_state(*other_tail);

    // Update the prev pointers.
    other_head_ns.prev_ = tgt_prev;
    tgt_prev = other_tail;

    // Update the next pointers.
    other_tail_ns.next_ = tgt_next;
    tgt_next = other_list.head_;

    // Mark the other list as being empty now by replacing its head pointer
    // with its sentinel value.
    other_list.head_ = other_list.sentinel();

    // Update our count bookkeeping.  Note: don't attempt to access
    // SizeTrackerCount() unless we are a list which supports constant order
    // size.  The method will not exist when we have O(N) access to our size.
    if constexpr (ListSizeOrder == SizeOrder::Constant) {
      this->IncSizeTracker(other_list.SizeTrackerCount());
      other_list.ResetSizeTracker();
    }
  }

  // Split the list immediately after |iter|, returning the remainder of the
  // list in a new list instance.
  //
  // |iter| *must* refer to a member of the list being split.  Attempt to split
  // list A with an iterator to an element which is a member of list B will
  // result in undefined behavior which may not be detectable at runtime.
  ContainerType split_after(const iterator& iter) {
    if (!iter.IsValid()) {
      // iter must refer to a member of this list, therefore it must be valid.
      // DEBUG_ASSERT if it is not, or return an empty list in a release build.
      ZX_DEBUG_ASSERT(false);
      return {};
    }
    return split_after(*iter.node_);
  }

  // Alternate form of split_after which uses an object reference instead of an
  // iterator to determine the split point.  Just like the iterator form of
  // split_after, |obj| *must* be a member of the list being split.
  ContainerType split_after(ValueType& obj) {
    static_assert(ListSizeOrder == SizeOrder::N,
                  "split_after is not allowed for SizedDoublyLinkedLists");
    auto& A_ns = NodeTraits::node_state(obj);

    // If this is element is already the tail of the list, or if it is an
    // illegal split in a release build, simply return an empty list.
    if (!A_ns.InContainer()) {
      ZX_DEBUG_ASSERT(false);
      return {};
    }

    if (internal::is_sentinel_ptr(A_ns.next_)) {
      // Since this node is at the end of the list, we can sanity check to make
      // sure that obj was actually a member of this list.
      ZX_DEBUG_ASSERT(A_ns.next_ == sentinel());
      return {};
    }

    // At this point in time, we know that we have at least 2 nodes in the list
    // we are splitting.  Let A be |obj|, and B be the node immediately after A.
    //
    // We have 5 pointers we need to update in total.
    //
    // ret.head       : needs to point to B, which is the new head of ret
    // A.next         : A is the new tail.  Next becomes this.sentinel();
    // B.prev         : B is the new head of ret.  Its prev points to ret.tail
    // this.head.prev : A is the new tail of this.  this.head.prev needs to point to it.
    // this.tail.next : this.tail is now ret.tail, so this.tail.next = ret.sentinel()
    ContainerType ret;
    auto& B_ns = NodeTraits::node_state(*A_ns.next_);
    auto& head_ns = NodeTraits::node_state(*head_);
    auto& tail_ns = NodeTraits::node_state(*head_ns.prev_);

    ret.head_ = A_ns.next_;
    A_ns.next_ = this->sentinel();
    B_ns.prev_ = head_ns.prev_;
    head_ns.prev_ = &obj;
    tail_ns.next_ = ret.sentinel();

    return ret;
  }

  // insert_after : Insert an element after iter in the list, and return
  // an element to the newly-inserted element.
  //
  // Note: It is an error to attempt to push a nullptr instance of PtrType, or
  // to attempt to push with iter == end().
  iterator insert_after(const iterator& iter, const PtrType& ptr) {
    return insert_after(iter, PtrType(ptr));
  }
  iterator insert_after(const iterator& iter, PtrType&& ptr) {
    ZX_DEBUG_ASSERT(iter.IsValid());

    auto& ns = NodeTraits::node_state(*iter.node_);
    return internal_insert(ns.next_, std::move(ptr));
  }

  // pop_front and pop_back
  //
  // Removes either the head or the tail of the list and transfers the pointer
  // to the caller.  If the list is empty, return a nullptr instance of
  // PtrType.
  PtrType pop_front() { return internal_erase(head_); }
  PtrType pop_back() { return internal_erase(tail()); }

  // erase
  //
  // Remove the element at the provided iterator and return a pointer to the
  // removed element.  If there is no element in the list at this position
  // (iter is end()), return a nullptr instance of PtrType.  It is an error to
  // attempt to use an iterator from a different instance of this list type to
  // attempt to erase a node.
  PtrType erase(ValueType& obj) { return internal_erase(&obj); }
  PtrType erase(const iterator& iter) { return internal_erase(iter.node_); }

  // erase_next
  //
  // Remove the element in the list which follows iter and return a pointer to
  // the removed element.  If there is no element in the list which follows
  // iter, return a nullptr instance of PtrType.  It is an error to attempt to
  // erase_next an invalid iterator (either an uninitialized iterator, or an
  // iterator which is equal to end()) It is an error to attempt to use an
  // iterator from a different instance of this list type to attempt to erase
  // a node.
  PtrType erase_next(const iterator& iter) {
    ZX_DEBUG_ASSERT(iter.IsValid());
    auto& ns = NodeTraits::node_state(*iter.node_);

    if (internal::is_sentinel_ptr(ns.next_)) {
      ZX_DEBUG_ASSERT(sentinel() == ns.next_);
      return PtrType(nullptr);
    }

    return internal_erase(ns.next_);
  }

  // clear
  //
  // Clear out the list, unlinking all of the elements in the process.  For
  // managed pointer types, this will release all references held by the list
  // to the objects which were in it.
  void clear() {
    while (!is_empty()) {
      auto& head_ns = NodeTraits::node_state(*head_);

      // Reclaim our pointer so that it will release its reference when it
      // goes out of scope a the end of the loop.  Note, this needs to be
      // flagged as UNUSED because for unmanaged pointer types, nothing
      // happens when the pointer goes out of scope.
      __UNUSED auto tmp = PtrTraits::Reclaim(head_);
      head_ = head_ns.next_;
      head_ns.next_ = nullptr;
      head_ns.prev_ = nullptr;
    }

    // Update our count bookkeeping.
    this->ResetSizeTracker();
  }

  // clear_unsafe
  //
  // See comments in fbl/intrusive_single_list.h
  // Think carefully before calling this!
  void clear_unsafe() {
    static_assert(PtrTraits::IsManaged == false,
                  "clear_unsafe is not allowed for containers of managed pointers");
    static_assert(NodeTraits::NodeState::kNodeOptions & NodeOptions::AllowClearUnsafe,
                  "Container does not support clear_unsafe.  Consider adding "
                  "NodeOptions::AllowClearUnsafe to your node storage.");

    head_ = sentinel();

    // Update our count bookkeeping.
    this->ResetSizeTracker();
  }

  // swap : swaps the contest of two lists.
  void swap(DoublyLinkedList& other) {
    internal::Swap(head_, other.head_);

    RawPtrType& sentinel_ptr = is_empty() ? head_ : NodeTraits::node_state(*tail()).next_;
    RawPtrType& other_sentinel_ptr =
        other.is_empty() ? other.head_ : NodeTraits::node_state(*other.tail()).next_;

    sentinel_ptr = sentinel();
    other_sentinel_ptr = other.sentinel();
    this->SwapSizeTracker(other);
  }

  // size_slow : count the elements in the list in O(n) fashion.
  size_t size_slow() const {
    // It is illegal to call this if the user requested constant order size
    // operations.
    static_assert(
        ListSizeOrder == SizeOrder::N,
        "size_slow is only allowed when using a list which has O(N) size!  Use size() instead.");

    size_t size = 0;

    for (auto iter = cbegin(); iter != cend(); ++iter) {
      size++;
    }

    return size;
  }

  // size : Only allowed when the user has selected an SizeOrder::Constant for this list.
  size_t size() const {
    static_assert(
        ListSizeOrder == SizeOrder::Constant,
        "size is only allowed when using a list which has O(1) size!  Use size_slow() instead.");
    return this->SizeTrackerCount();
  }

  // erase_if
  //
  // Find the first member of the list which satisfies the predicate given by
  // 'fn' and remove it from the list, returning a referenced pointer to the
  // removed element.  Return nullptr if no element satisfies the predicate.
  template <typename UnaryFn>
  PtrType erase_if(UnaryFn fn) {
    for (auto iter = begin(); iter != end(); ++iter)
      if (fn(static_cast<typename PtrTraits::ConstRefType>(*iter)))
        return erase(iter);

    return PtrType(nullptr);
  }

  // find_if
  //
  // Find the first member of the list which satisfies the predicate given by
  // 'fn' and return an iterator in the list which refers to it.  Return end()
  // if no member satisfies the predicate.
  template <typename UnaryFn>
  const_iterator find_if(UnaryFn fn) const {
    for (auto iter = begin(); iter.IsValid(); ++iter) {
      if (fn(*iter))
        return iter;
    }

    return end();
  }

  template <typename UnaryFn>
  iterator find_if(UnaryFn fn) {
    const_iterator citer = const_cast<const ContainerType*>(this)->find_if(fn);
    return iterator(citer.node_);
  }

  // replace_if (copy)
  //
  // Find the first member of the list which satisfies the predicate given by
  // 'fn' and replace it in the list, returning a referenced pointer to the
  // replaced element.  If no member satisfies the predicate, simply return
  // nullptr instead.
  template <typename UnaryFn>
  PtrType replace_if(UnaryFn fn, const PtrType& ptr) {
    iterator iter = find_if(fn);

    if (!iter.IsValid())
      return nullptr;

    return internal_swap(*iter, PtrType(ptr));
  }

  // replace_if (move)
  //
  // Same as the copy version, except that if no member satisfies the
  // predicate, the original reference is returned instead of nullptr.
  template <typename UnaryFn>
  PtrType replace_if(UnaryFn fn, PtrType&& ptr) {
    iterator iter = find_if(fn);

    if (!iter.IsValid())
      return std::move(ptr);

    return internal_swap(*iter, std::move(ptr));
  }

  // replace (copy and move)
  //
  // Replaces the target member of the list with the given replacement.
  PtrType replace(typename PtrTraits::RefType target, PtrType replacement) {
    return internal_swap(target, std::move(replacement));
  }

 private:
  // The traits of a non-const iterator
  struct iterator_traits {
    using RefType = typename PtrTraits::RefType;
    using RawPtrType = typename PtrTraits::RawPtrType;
  };

  // The traits of a const iterator
  struct const_iterator_traits {
    using RefType = typename PtrTraits::ConstRefType;
    using RawPtrType = typename PtrTraits::ConstRawPtrType;
  };

  // The shared implementation of the iterator
  template <class IterTraits>
  class iterator_impl {
   public:
    iterator_impl() = default;
    iterator_impl(const iterator_impl& other) = default;
    iterator_impl& operator=(const iterator_impl& other) = default;

    bool IsValid() const { return !internal::is_sentinel_ptr(node_) && (node_ != nullptr); }
    bool operator==(const iterator_impl& other) const { return node_ == other.node_; }
    bool operator!=(const iterator_impl& other) const { return node_ != other.node_; }

    // Prefix
    iterator_impl& operator++() {
      if (IsValid()) {
        auto& ns = NodeTraits::node_state(*node_);
        node_ = ns.next_;
        ZX_DEBUG_ASSERT(node_ != nullptr);
      }

      return *this;
    }

    iterator_impl& operator--() {
      if (node_) {
        if (internal::is_sentinel_ptr(node_)) {
          auto list = unmake_sentinel(node_);
          node_ = list->tail();
        } else {
          auto& ns = NodeTraits::node_state(*node_);
          node_ = ns.prev_;
          ZX_DEBUG_ASSERT(node_ != nullptr);

          // If backing up would put us at a node whose next pointer
          // is a sentinel, the we have looped around the start of the
          // list and are currently pointed at the tail of the list.
          // Reset our internal pointer to point to the sentinel value
          // instead.
          auto& new_ns = NodeTraits::node_state(*node_);
          if (internal::is_sentinel_ptr(new_ns.next_))
            node_ = new_ns.next_;
        }
      }

      return *this;
    }

    // Postfix
    iterator_impl operator++(int) {
      iterator_impl ret(*this);
      ++(*this);
      return ret;
    }

    iterator_impl operator--(int) {
      iterator_impl ret(*this);
      --(*this);
      return ret;
    }

    typename PtrTraits::PtrType CopyPointer() const {
      return IsValid() ? PtrTraits::Copy(node_) : nullptr;
    }

    typename IterTraits::RefType operator*() const {
      ZX_DEBUG_ASSERT(IsValid());
      return *node_;
    }

    typename IterTraits::RawPtrType operator->() const {
      ZX_DEBUG_ASSERT(IsValid());
      return node_;
    }

   private:
    friend class DoublyLinkedList<PtrType_, TagType_, ListSizeOrder_, NodeTraits_>;
    using ListType = const DoublyLinkedList<PtrType_, TagType_, ListSizeOrder_, NodeTraits_>;

    iterator_impl(const typename PtrTraits::RawPtrType node)
        : node_(const_cast<typename PtrTraits::RawPtrType>(node)) {}

    const ListType* unmake_sentinel(typename PtrTraits::RawPtrType p) {
      return static_cast<const ListType*>(internal::unmake_sentinel<typename ListType::Base*>(p));
    }

    typename PtrTraits::RawPtrType node_ = nullptr;
  };

  // The test framework's 'checker' class is our friend.
  friend CheckerType;

  // move semantics only
  DoublyLinkedList(const DoublyLinkedList&) = delete;
  DoublyLinkedList& operator=(const DoublyLinkedList&) = delete;

  constexpr RawPtrType sentinel() const { return internal::make_sentinel<RawPtrType>(this); }

  iterator internal_insert(RawPtrType before, PtrType&& ptr) {
    ZX_DEBUG_ASSERT(ptr != nullptr);
    ZX_DEBUG_ASSERT(before != nullptr);
    ZX_DEBUG_ASSERT(head_ != nullptr);

    auto& ptr_ns = NodeTraits::node_state(*ptr);
    ZX_DEBUG_ASSERT((ptr_ns.prev_ == nullptr) && (ptr_ns.next_ == nullptr));

    // No matter what happens, we are going to be 1 larger after this operation.
    this->IncSizeTracker(1);

    // Handle the (slightly) special case of an empty list.
    if (is_empty()) {
      ZX_DEBUG_ASSERT(before == sentinel());
      ZX_DEBUG_ASSERT(before == head_);

      auto* new_item = PtrTraits::Leak(ptr);
      ptr_ns.prev_ = new_item;
      ptr_ns.next_ = head_;
      head_ = new_item;

      return make_iterator(*new_item);
    }

    // If we are being inserted before the sentinel, the we are the new
    // tail, and the node_state which contains the prev pointer we need to
    // update is head's.  Otherwise, it is the node_state of the node we are
    // being inserted before.
    auto& prev_ns = NodeTraits::node_state(internal::is_sentinel_ptr(before) ? *head_ : *before);
    auto& tgt_prev = prev_ns.prev_;

    // If we are being inserted before the head, then we need to update the
    // managed head pointer.  Otherwise, we need to update the next pointer
    // of the node which is about to come before us.
    auto& tgt_next = (head_ == before)                   ? head_
                     : internal::is_sentinel_ptr(before) ? NodeTraits::node_state(*tail()).next_
                                                         : NodeTraits::node_state(*tgt_prev).next_;

    // Update the pointers in the inserted node.
    ptr_ns.next_ = tgt_next;
    ptr_ns.prev_ = tgt_prev;

    // Update the pointers which should now point to the inserted node.
    auto* new_item = PtrTraits::Leak(ptr);
    tgt_next = new_item;
    tgt_prev = new_item;

    // Return an iterator to the new element.
    return make_iterator(*new_item);
  }

  PtrType internal_erase(RawPtrType node) {
    if (!node || internal::is_sentinel_ptr(node)) {
      return PtrType(nullptr);
    }

    // No matter what happens after this, we are going to be 1 smaller after this operation.
    this->DecSizeTracker(1);

    // Defer to our base implementation in order to remove this node.
    return Base::template internal_erase<NodeTraits>(NodeTraits::node_state(*node));
  }

  PtrType internal_swap(typename PtrTraits::RefType node, PtrType&& ptr) {
    ZX_DEBUG_ASSERT(ptr != nullptr);
    auto& ptr_ns = NodeTraits::node_state(*ptr);
    ZX_DEBUG_ASSERT(!ptr_ns.InContainer());

    auto& node_ns = NodeTraits::node_state(node);
    ZX_DEBUG_ASSERT(node_ns.InContainer());

    // Handle the case of there being only a single node in the list.
    ZX_DEBUG_ASSERT(internal::valid_sentinel_ptr(head_));
    if (internal::is_sentinel_ptr(NodeTraits::node_state(*head_).next_)) {
      ZX_DEBUG_ASSERT(head_ == &node);
      ZX_DEBUG_ASSERT(internal::is_sentinel_ptr(node_ns.next_));
      ZX_DEBUG_ASSERT(&node == node_ns.prev_);

      ptr_ns.next_ = node_ns.next_;
      ptr_ns.prev_ = PtrTraits::GetRaw(ptr);
      node_ns.next_ = nullptr;
      node_ns.prev_ = nullptr;

      head_ = PtrTraits::Leak(ptr);
      return PtrTraits::Reclaim(&node);
    }

    // Find the prev pointer we need to update.  If we are swapping the tail
    // of the list, the prev pointer is head_'s prev pointer.  Otherwise, it
    // is the prev pointer of the node which currently follows "ptr".
    auto& tgt_prev = internal::is_sentinel_ptr(node_ns.next_)
                         ? NodeTraits::node_state(*head_).prev_
                         : NodeTraits::node_state(*node_ns.next_).prev_;

    // Find the next pointer we need to update.  If we are swapping the
    // head of the list, this is head_.  Otherwise it is the next pointer of
    // the node which comes before us in the list.
    auto& tgt_next = (head_ == &node) ? head_ : NodeTraits::node_state(*node_ns.prev_).next_;

    tgt_next = PtrTraits::Leak(ptr);
    tgt_prev = tgt_next;
    internal::Swap(ptr_ns.next_, node_ns.next_);
    internal::Swap(ptr_ns.prev_, node_ns.prev_);

    return PtrTraits::Reclaim(&node);
  }

  RawPtrType tail() const {
    ZX_DEBUG_ASSERT(head_ != nullptr);
    if (internal::is_sentinel_ptr(head_))
      return head_;
    return NodeTraits::node_state(*head_).prev_;
  }

  using Base::head_;
  using Base::sentinel;
};

// SizedDoublyLinkedList<> is an alias for a DoublyLinkedList<> which keeps
// track of it's size internally so that it may be accessed in O(1) time.
//
template <typename PtrType, typename TagType = DefaultObjectTag,
          typename NodeTraits = DefaultDoublyLinkedListTraits<PtrType, TagType>>
using SizedDoublyLinkedList = DoublyLinkedList<PtrType, TagType, SizeOrder::Constant, NodeTraits>;

// DoublyLinkedListCustomTraits<> is an alias for a DoublyLinkedList<> which makes is easier to
// define a DoublyLinkedList which uses custom node traits.  It defaults to O(n) size, and will not
// allow users to use a non-default object tag, since lists which use custom node traits are
// required to use the default tag.
//
template <typename PtrType, typename NodeTraits, SizeOrder ListSizeOrder = SizeOrder::N>
using DoublyLinkedListCustomTraits =
    DoublyLinkedList<PtrType, DefaultObjectTag, ListSizeOrder, NodeTraits>;

// TaggedDoublyLinkedList<> is intended for use with ContainableBaseClasses<>.
//
// For an easy way to allow instances of your class to live in multiple
// intrusive containers at once, simply derive from
// ContainableBaseClasses<YourContainables<PtrType, TagType>...> and then use
// this template instead of DoublyLinkedList<> as the container, passing the same tag
// type you used earlier as the third parameter.
//
// See comments on ContainableBaseClasses<> in fbl/intrusive_container_utils.h
// for more details.
//
template <typename PtrType, typename TagType>
using TaggedDoublyLinkedList = DoublyLinkedList<PtrType, TagType, SizeOrder::N,
                                                DefaultDoublyLinkedListTraits<PtrType, TagType>>;

template <typename PtrType, typename TagType, NodeOptions Options = NodeOptions::None>
using TaggedDoublyLinkedListable = DoublyLinkedListable<PtrType, Options, TagType>;

}  // namespace fbl

#endif  // FBL_INTRUSIVE_DOUBLE_LIST_H_
