// 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 #include "src/base/logging.h" namespace v8 { namespace internal { namespace heap { template 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 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; }; } // namespace heap } // namespace internal } // namespace v8 #endif // V8_HEAP_LIST_H_