/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
deps/v8/src/base/doubly-threaded-list.h
152 строки
4 KB
Michaël Zasso
deps: update V8 to 13.7.152.9
18 май 2025, 10:42
18 май 2025, 10:42
fff0d15
Код
Авторство
О чём код?
// Copyright 2023 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_BASE_DOUBLY_THREADED_LIST_H_ #define V8_BASE_DOUBLY_THREADED_LIST_H_ #include "src/base/compiler-specific.h" #include "src/base/iterator.h" #include "src/base/logging.h" namespace v8::base { template <typename T> struct DoublyThreadedListTraits { static T** prev(T t) { return t->prev(); } static T* next(T t) { return t->next(); } static bool non_empty(T t) { return t != nullptr; } }; // `DoublyThreadedList` is an intrusive doubly-linked list that threads through // its nodes, somewhat like `v8::base::ThreadedList`. // // Of interest is the fact that instead of having regular next/prev pointers, // nodes have a regular "next" pointer, but their "prev" pointer contains the // address of the "next" of the previous element. This way, removing an element // doesn't require special treatment for the head of the list, and does not // even require to know the head of the list. template <class T, class DTLTraits = DoublyThreadedListTraits<T>> class DoublyThreadedList { public: // Since C++17, it is possible to have a sentinel end-iterator that is not an // iterator itself. class end_iterator {}; class iterator : public base::iterator<std::forward_iterator_tag, T> { public: explicit iterator(T head) : curr_(head) {} T operator*() { return curr_; } iterator& operator++() { DCHECK(DTLTraits::non_empty(curr_)); curr_ = *DTLTraits::next(curr_); return *this; } iterator operator++(int) { DCHECK(DTLTraits::non_empty(curr_)); iterator tmp(*this); operator++(); return tmp; } bool operator==(end_iterator) { return !DTLTraits::non_empty(curr_); } private: friend DoublyThreadedList; T curr_; }; // Removes `x` from the list. Iterators that are currently on `x` are // invalidated. To remove while iterating, use RemoveAt. static void Remove(T x) { if (*DTLTraits::prev(x) == nullptr) { DCHECK(empty(*DTLTraits::next(x))); // {x} already removed from the list. return; } T** prev = DTLTraits::prev(x); T* next = DTLTraits::next(x); **prev = *next; if (DTLTraits::non_empty(*next)) *DTLTraits::prev(*next) = *prev; *DTLTraits::prev(x) = nullptr; *DTLTraits::next(x) = {}; } DoublyThreadedList() = default; // Defining move constructor so that when resizing container, the prev pointer // of the next(head_) doesn't point to the old head_ but rather to the new // one. DoublyThreadedList(DoublyThreadedList&& other) V8_NOEXCEPT { head_ = other.head_; if (DTLTraits::non_empty(head_)) { *DTLTraits::prev(head_) = &head_; } other.head_ = {}; } // Add `x` at the beginning of the list. `x` will not be visible to any // existing iterator. Does not invalidate any existing iterator. void PushFront(T x) { DCHECK(empty(*DTLTraits::next(x))); DCHECK_EQ(*DTLTraits::prev(x), nullptr); *DTLTraits::next(x) = head_; *DTLTraits::prev(x) = &head_; if (DTLTraits::non_empty(head_)) { *DTLTraits::prev(head_) = DTLTraits::next(x); } head_ = x; } T Front() const { DCHECK(!empty()); return *begin(); } void PopFront() { DCHECK(!empty()); Remove(Front()); } bool empty() const { return !DTLTraits::non_empty(head_); } iterator begin() const { return iterator{head_}; } end_iterator end() const { return end_iterator{}; } // Removes the element at `it`, and make `it` point to the next element. // Iterators on the same element as `it` are invalidated. Other iterators are // not affected. iterator RemoveAt(iterator& it) { DCHECK(DTLTraits::non_empty(it.curr_)); T curr = *it; T next = *DTLTraits::next(curr); Remove(curr); return iterator{next}; } bool Contains(T needle) const { const bool in_use = DTLTraits::in_use(needle); DCHECK_EQ(in_use, ContainsSlow(needle)); return in_use; } bool ContainsSlow(T needle) const { for (T element : *this) { if (element == needle) { return true; } } return false; } private: static bool empty(T x) { return !DTLTraits::non_empty(x); } T head_{}; }; } // namespace v8::base #endif // V8_BASE_DOUBLY_THREADED_LIST_H_