// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_VM_INTRUSIVE_DLIST_H_
#define RUNTIME_VM_INTRUSIVE_DLIST_H_

#include "platform/assert.h"
#include "platform/globals.h"

namespace dart {

// Abstraction for "intrusive" doubly-linked list in a type-safe way in C++.
//
// By "intrusive" we mean that a class Item containing various field members
// has also next/previous pointers to the next/previous Item.
//
// To change a class Item to be part of such a doubly-linked list, one only
// needs to inherit from IntrusiveDListEntry<Item> (in addition to the normal
// base class).
//
// To change a class Item to be part of multiple doubly-linked lists, one can
// inherit multiple times from IntrusiveDListEntry<Item, N>, each time with a
// different value for <N>.
//
// To insert an object into a list, one uses a IntrusiveDList<Item, N>. It
// provides support for insertion/iteration/deletion.
//
// Usage example:
//
//    class Base {
//      <arbitrary state here>
//    };
//
//    class Item : public Base,
//                 public IntrusiveDListEntry<Item>,
//                 public IntrusiveDListEntry<Item, 2> {
//      <arbitrary state here>
//    };
//
//    Item a1, a2, a3;
//
//    IntrusiveDList<Item> all;
//    all.Append(a2);
//    all.Prepend(a1);
//    all.Append(a3);
//
//    IntrusiveDList<Item, 2> idle, ready;
//    idle.Append(a1);
//    ready.Append(a2);
//    ready.Append(a3);
//

template <typename T, int N>
class IntrusiveDList;

template <typename T, int N = 1>
class IntrusiveDListEntry {
 public:
  IntrusiveDListEntry() {}

  ~IntrusiveDListEntry() {
    // Either this is an unlinked entry or a head/anchor.
    ASSERT((next_ == nullptr && prev_ == nullptr) ||
           (next_ == this && prev_ == this));
  }

 private:
  void MakeHead() {
    ASSERT(next_ == nullptr && prev_ == nullptr);
    next_ = prev_ = this;
  }

  // This uses the C++ compiler's ability to convert between classes inside a
  // (possibly multi-) inheritance hierarchy.
  //
  // The non-typesafe C equivalent of this is:
  //
  //     ((uint8*)this) - offsetof(ContainerType, list_entry);
  //
  T* container() { return static_cast<T*>(this); }

  void Append(IntrusiveDListEntry<T, N>* entry) {
    ASSERT(entry->next_ == nullptr && entry->prev_ == nullptr);
    entry->next_ = next_;
    entry->prev_ = this;
    next_ = entry;
    entry->next_->prev_ = entry;
  }

  void Prepend(IntrusiveDListEntry<T, N>* entry) {
    ASSERT(entry->next_ == nullptr && entry->prev_ == nullptr);
    entry->next_ = this;
    entry->prev_ = prev_;
    prev_ = entry;
    entry->prev_->next_ = entry;
  }

  void Remove() {
    ASSERT(prev_->next_ == this);
    ASSERT(next_->prev_ == this);
    ASSERT(prev_ != this && next_ != this);

    prev_->next_ = next_;
    next_->prev_ = prev_;

    next_ = nullptr;
    prev_ = nullptr;
  }

  bool IsEmpty() {
    bool result = next_ == this;
    ASSERT(result == (prev_ == this));
    return result;
  }

  bool IsLinked() {
    ASSERT((next_ == nullptr) == (prev_ == nullptr));
    return next_ != nullptr;
  }

  IntrusiveDListEntry<T, N>* Prev() { return prev_; }

  IntrusiveDListEntry<T, N>* Next() { return next_; }

  friend class IntrusiveDList<T, N>;

  IntrusiveDListEntry<T, N>* next_ = nullptr;
  IntrusiveDListEntry<T, N>* prev_ = nullptr;

  DISALLOW_COPY_AND_ASSIGN(IntrusiveDListEntry);
};

template <typename T, int N = 1>
class IntrusiveDList {
 public:
  typedef IntrusiveDListEntry<T, N> Entry;

  template <typename ContainerType, int I = 1>
  class Iterator {
   public:
    Iterator(IntrusiveDList<ContainerType, I>* head,
             IntrusiveDListEntry<ContainerType, I>* entry)
        : head_(head), entry_(entry) {}

    inline ContainerType* operator->() { return entry_->container(); }

    inline ContainerType* operator*() { return entry_->container(); }

    inline bool operator==(const Iterator<ContainerType, I>& other) const {
      return entry_ == other.entry_;
    }

    inline bool operator!=(const Iterator<ContainerType, I>& other) const {
      return !(*this == other);
    }

    inline Iterator<ContainerType, I>& operator++() {
      entry_ = entry_->Next();
      return *this;
    }

    inline Iterator<ContainerType, I>& operator--() {
      entry_ = entry_->Prev();
      return *this;
    }

   private:
    friend IntrusiveDList;

    IntrusiveDList<ContainerType, I>* head_;
    IntrusiveDListEntry<ContainerType, I>* entry_;
  };

  inline IntrusiveDList() { head_.MakeHead(); }

  inline void Append(T* a) { head_.Prepend(convert(a)); }

  inline void Prepend(T* a) { head_.Append(convert(a)); }

  // NOTE: This function only checks whether [a] is linked inside *a*
  // [IntrusiveDList].
  inline bool IsInList(T* a) { return convert(a)->IsLinked(); }

  inline void Remove(T* a) { convert(a)->Remove(); }

  inline bool IsEmpty() { return head_.IsEmpty(); }

  inline T* First() {
    ASSERT(!IsEmpty());
    return head_.Next()->container();
  }

  inline T* Last() {
    ASSERT(!IsEmpty());
    return head_.Prev()->container();
  }

  inline T* RemoveFirst() {
    ASSERT(!IsEmpty());
    auto entry = head_.Next();
    T* container = entry->container();
    entry->Remove();
    return container;
  }

  inline T* RemoveLast() {
    ASSERT(!IsEmpty());
    auto entry = head_.Prev();
    T* container = entry->container();
    entry->Remove();
    return container;
  }

  inline Iterator<T, N> Begin() { return Iterator<T, N>(this, head_.Next()); }

  inline Iterator<T, N> End() { return Iterator<T, N>(this, &head_); }

  inline Iterator<T, N> begin() { return Begin(); }

  inline Iterator<T, N> end() { return End(); }

  inline Iterator<T, N> Erase(const Iterator<T, N>& iterator) {
    ASSERT(iterator.head_ == this);
    Iterator<T, N> next(this, iterator.entry_->Next());
    iterator.entry_->Remove();
    return next;
  }

 private:
  Entry head_;

  Entry* convert(T* entry) { return static_cast<Entry*>(entry); }
};

}  // namespace dart.

#endif  // RUNTIME_VM_INTRUSIVE_DLIST_H_
