// Copyright 2018 the V8 project 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 V8_HEAP_LIST_H_
#define V8_HEAP_LIST_H_

#include <atomic>

#include "src/base/logging.h"

namespace v8 {
namespace internal {
namespace heap {

template <class T>
class List {
 public:
  List() : front_(nullptr), back_(nullptr) {}
  List(List&& other) V8_NOEXCEPT : front_(std::exchange(other.front_, nullptr)),
                                   back_(std::exchange(other.back_, nullptr)) {}
  List& operator=(List&& other) V8_NOEXCEPT {
    front_ = std::exchange(other.front_, nullptr);
    back_ = std::exchange(other.back_, nullptr);
    return *this;
  }

  void ShallowCopyTo(List* other) const {
    other->front_ = front_;
    other->back_ = back_;
  }

  void PushBack(T* element) {
    DCHECK(!element->list_node().next());
    DCHECK(!element->list_node().prev());
    if (back_) {
      DCHECK(front_);
      InsertAfter(element, back_);
    } else {
      AddFirstElement(element);
    }
  }

  void PushFront(T* element) {
    DCHECK(!element->list_node().next());
    DCHECK(!element->list_node().prev());
    if (front_) {
      DCHECK(back_);
      InsertBefore(element, front_);
    } else {
      AddFirstElement(element);
    }
  }

  void Remove(T* element) {
    DCHECK(Contains(element));
    if (back_ == element) {
      back_ = element->list_node().prev();
    }
    if (front_ == element) {
      front_ = element->list_node().next();
    }
    T* next = element->list_node().next();
    T* prev = element->list_node().prev();
    if (next) next->list_node().set_prev(prev);
    if (prev) prev->list_node().set_next(next);
    element->list_node().set_prev(nullptr);
    element->list_node().set_next(nullptr);
  }

  bool Contains(T* element) const {
    const T* it = front_;
    while (it) {
      if (it == element) return true;
      it = it->list_node().next();
    }
    return false;
  }

  bool Empty() const { return !front_ && !back_; }

  T* front() { return front_; }
  T* back() { return back_; }

  const T* front() const { return front_; }
  const T* back() const { return back_; }

 private:
  void AddFirstElement(T* element) {
    DCHECK(!back_);
    DCHECK(!front_);
    DCHECK(!element->list_node().next());
    DCHECK(!element->list_node().prev());
    element->list_node().set_prev(nullptr);
    element->list_node().set_next(nullptr);
    front_ = element;
    back_ = element;
  }

  void InsertAfter(T* element, T* other) {
    T* other_next = other->list_node().next();
    element->list_node().set_next(other_next);
    element->list_node().set_prev(other);
    other->list_node().set_next(element);
    if (other_next)
      other_next->list_node().set_prev(element);
    else
      back_ = element;
  }

  void InsertBefore(T* element, T* other) {
    T* other_prev = other->list_node().prev();
    element->list_node().set_next(other);
    element->list_node().set_prev(other_prev);
    other->list_node().set_prev(element);
    if (other_prev) {
      other_prev->list_node().set_next(element);
    } else {
      front_ = element;
    }
  }

  T* front_;
  T* back_;
};

template <class T>
class ListNode {
 public:
  ListNode() { Initialize(); }

  T* next() { return next_; }
  T* prev() { return prev_; }

  const T* next() const { return next_; }
  const T* prev() const { return prev_; }

  void Initialize() {
    next_ = nullptr;
    prev_ = nullptr;
  }

 private:
  void set_next(T* next) { next_ = next; }
  void set_prev(T* prev) { prev_ = prev; }

  T* next_;
  T* prev_;

  friend class List<T>;
};
}  // namespace heap
}  // namespace internal
}  // namespace v8

#endif  // V8_HEAP_LIST_H_
