1d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko/* 2d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko * Copyright (C) 2016 The Android Open Source Project 3d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko * 4d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko * Licensed under the Apache License, Version 2.0 (the "License"); 5d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko * you may not use this file except in compliance with the License. 6d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko * You may obtain a copy of the License at 7d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko * 8d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko * http://www.apache.org/licenses/LICENSE-2.0 9d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko * 10d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko * Unless required by applicable law or agreed to in writing, software 11d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko * distributed under the License is distributed on an "AS IS" BASIS, 12d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko * See the License for the specific language governing permissions and 14d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko * limitations under the License. 15d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko */ 16d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 17d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko#ifndef ART_COMPILER_UTILS_INTRUSIVE_FORWARD_LIST_H_ 18d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko#define ART_COMPILER_UTILS_INTRUSIVE_FORWARD_LIST_H_ 19d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 20d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko#include <stdint.h> 21d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko#include <functional> 22d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko#include <iterator> 23d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko#include <memory> 24d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko#include <type_traits> 25d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 26d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko#include "base/logging.h" 27d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko#include "base/macros.h" 28d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 29d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markonamespace art { 30d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 31d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markostruct IntrusiveForwardListHook { 32d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardListHook() : next_hook(nullptr) { } 33d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko explicit IntrusiveForwardListHook(const IntrusiveForwardListHook* hook) : next_hook(hook) { } 34d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 35d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Allow copyable values but do not copy the hook, it is not part of the value. 36d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardListHook(const IntrusiveForwardListHook& other ATTRIBUTE_UNUSED) 37d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko : next_hook(nullptr) { } 38d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardListHook& operator=(const IntrusiveForwardListHook& src ATTRIBUTE_UNUSED) { 39d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return *this; 40d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 41d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 42d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko mutable const IntrusiveForwardListHook* next_hook; 43d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko}; 44d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 45d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markotemplate <typename T, IntrusiveForwardListHook T::* NextPtr = &T::hook> 46d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markoclass IntrusiveForwardListMemberHook; 47d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 48d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markotemplate <typename T, typename HookTraits = IntrusiveForwardListMemberHook<T>> 49d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markoclass IntrusiveForwardList; 50d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 51d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markotemplate <typename T, typename HookTraits> 52d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markoclass IntrusiveForwardListIterator : public std::iterator<std::forward_iterator_tag, T> { 53d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko public: 54d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Construct/copy/destroy (except the private constructor used by IntrusiveForwardList<>). 55d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardListIterator() : hook_(nullptr) { } 56d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardListIterator(const IntrusiveForwardListIterator& src) = default; 57d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardListIterator& operator=(const IntrusiveForwardListIterator& src) = default; 58d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 59d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Conversion from iterator to const_iterator. 60d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko template <typename OtherT, 61d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko typename = typename std::enable_if<std::is_same<T, const OtherT>::value>::type> 62d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardListIterator(const IntrusiveForwardListIterator<OtherT, HookTraits>& src) 63d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko : hook_(src.hook_) { } 64d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 65d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Iteration. 66d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardListIterator& operator++() { 67d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko DCHECK(hook_ != nullptr); 68d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko hook_ = hook_->next_hook; 69d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return *this; 70d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 71d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardListIterator operator++(int) { 72d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardListIterator tmp(*this); 73d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko ++*this; 74d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return tmp; 75d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 76d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 77d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Dereference 78d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko T& operator*() const { 79d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko DCHECK(hook_ != nullptr); 80d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return *HookTraits::GetValue(hook_); 81d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 82d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko T* operator->() const { 83d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return &**this; 84d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 85d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 86d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko private: 87d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko explicit IntrusiveForwardListIterator(const IntrusiveForwardListHook* hook) : hook_(hook) { } 88d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 89d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const IntrusiveForwardListHook* hook_; 90d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 91d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko template <typename OtherT, typename OtherTraits> 92d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko friend class IntrusiveForwardListIterator; 93d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 94d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko template <typename OtherT, typename OtherTraits> 95d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko friend class IntrusiveForwardList; 96d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 97d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko template <typename OtherT1, typename OtherT2, typename OtherTraits> 98d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko friend typename std::enable_if<std::is_same<const OtherT1, const OtherT2>::value, bool>::type 99d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko operator==(const IntrusiveForwardListIterator<OtherT1, OtherTraits>& lhs, 100d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const IntrusiveForwardListIterator<OtherT2, OtherTraits>& rhs); 101d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko}; 102d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 103d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markotemplate <typename T, typename OtherT, typename HookTraits> 104d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markotypename std::enable_if<std::is_same<const T, const OtherT>::value, bool>::type operator==( 105d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const IntrusiveForwardListIterator<T, HookTraits>& lhs, 106d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const IntrusiveForwardListIterator<OtherT, HookTraits>& rhs) { 107d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return lhs.hook_ == rhs.hook_; 108d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko} 109d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 110d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markotemplate <typename T, typename OtherT, typename HookTraits> 111d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markotypename std::enable_if<std::is_same<const T, const OtherT>::value, bool>::type operator!=( 112d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const IntrusiveForwardListIterator<T, HookTraits>& lhs, 113d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const IntrusiveForwardListIterator<OtherT, HookTraits>& rhs) { 114d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return !(lhs == rhs); 115d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko} 116d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 117d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko// Intrusive version of std::forward_list<>. See also slist<> in Boost.Intrusive. 118d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko// 119d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko// This class template provides the same interface as std::forward_list<> as long 120d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko// as the functions are meaningful for an intrusive container; this excludes emplace 121d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko// functions and functions taking an std::initializer_list<> as the container does 122d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko// not construct elements. 123d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markotemplate <typename T, typename HookTraits> 124d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markoclass IntrusiveForwardList { 125d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko public: 126d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko typedef HookTraits hook_traits; 127d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko typedef T value_type; 128d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko typedef T& reference; 129d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko typedef const T& const_reference; 130d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko typedef T* pointer; 131d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko typedef const T* const_pointer; 132d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko typedef IntrusiveForwardListIterator< T, hook_traits> iterator; 133d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko typedef IntrusiveForwardListIterator<const T, hook_traits> const_iterator; 134d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 135d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Construct/copy/destroy. 136d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardList() = default; 137d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko template <typename InputIterator> 138d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardList(InputIterator first, InputIterator last) : IntrusiveForwardList() { 139d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko insert_after(before_begin(), first, last); 140d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 141d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardList(IntrusiveForwardList&& src) : first_(src.first_.next_hook) { 142d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko src.first_.next_hook = nullptr; 143d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 144d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardList& operator=(const IntrusiveForwardList& src) = delete; 145d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardList& operator=(IntrusiveForwardList&& src) { 146d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardList tmp(std::move(src)); 147d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko tmp.swap(*this); 148d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return *this; 149d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 150d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko ~IntrusiveForwardList() = default; 151d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 152d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Iterators. 153d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko iterator before_begin() { return iterator(&first_); } 154d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const_iterator before_begin() const { return const_iterator(&first_); } 155d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko iterator begin() { return iterator(first_.next_hook); } 156d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const_iterator begin() const { return const_iterator(first_.next_hook); } 157d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko iterator end() { return iterator(nullptr); } 158d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const_iterator end() const { return const_iterator(nullptr); } 159d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const_iterator cbefore_begin() const { return const_iterator(&first_); } 160d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const_iterator cbegin() const { return const_iterator(first_.next_hook); } 161d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const_iterator cend() const { return const_iterator(nullptr); } 162d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 163d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Capacity. 164d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko bool empty() const { return begin() == end(); } 165d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko size_t max_size() { return static_cast<size_t>(-1); } 166d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 167d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Element access. 168d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko reference front() { return *begin(); } 169d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const_reference front() const { return *begin(); } 170d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 171d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Modifiers. 172d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko template <typename InputIterator> 173d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void assign(InputIterator first, InputIterator last) { 174d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardList tmp(first, last); 175d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko tmp.swap(*this); 176d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 177d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void push_front(value_type& value) { 178d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko insert_after(before_begin(), value); 179d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 180d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void pop_front() { 181d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko DCHECK(!empty()); 182d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko erase_after(before_begin()); 183d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 184d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko iterator insert_after(const_iterator position, value_type& value) { 185d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const IntrusiveForwardListHook* new_hook = hook_traits::GetHook(&value); 186d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko new_hook->next_hook = position.hook_->next_hook; 187d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko position.hook_->next_hook = new_hook; 188d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return iterator(new_hook); 189d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 190d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko template <typename InputIterator> 191d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko iterator insert_after(const_iterator position, InputIterator first, InputIterator last) { 192d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko while (first != last) { 193d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko position = insert_after(position, *first++); 194d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 195d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return iterator(position.hook_); 196d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 197d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko iterator erase_after(const_iterator position) { 198d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const_iterator last = position; 199d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko std::advance(last, 2); 200d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return erase_after(position, last); 201d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 202d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko iterator erase_after(const_iterator position, const_iterator last) { 203d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko DCHECK(position != last); 204d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko position.hook_->next_hook = last.hook_; 205d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return iterator(last.hook_); 206d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 207d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void swap(IntrusiveForwardList& other) { 208d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko std::swap(first_.next_hook, other.first_.next_hook); 209d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 210d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void clear() { 211d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko first_.next_hook = nullptr; 212d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 213d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 214d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Operations. 215d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void splice_after(const_iterator position, IntrusiveForwardList& src) { 216d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko DCHECK(position != end()); 217d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko splice_after(position, src, src.before_begin(), src.end()); 218d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 219d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void splice_after(const_iterator position, IntrusiveForwardList&& src) { 220d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko splice_after(position, src); // Use l-value overload. 221d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 222d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Splice the element after `i`. 223d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void splice_after(const_iterator position, IntrusiveForwardList& src, const_iterator i) { 2249ef26544e6d9c438b150dfda39be61a7b4fd8b20Vladimir Marko // The standard specifies that this version does nothing if `position == i` 2259ef26544e6d9c438b150dfda39be61a7b4fd8b20Vladimir Marko // or `position == ++i`. We must handle the latter here because the overload 2269ef26544e6d9c438b150dfda39be61a7b4fd8b20Vladimir Marko // `splice_after(position, src, first, last)` does not allow `position` inside 2279ef26544e6d9c438b150dfda39be61a7b4fd8b20Vladimir Marko // the range `(first, last)`. 2289ef26544e6d9c438b150dfda39be61a7b4fd8b20Vladimir Marko if (++const_iterator(i) == position) { 2299ef26544e6d9c438b150dfda39be61a7b4fd8b20Vladimir Marko return; 2309ef26544e6d9c438b150dfda39be61a7b4fd8b20Vladimir Marko } 231d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const_iterator last = i; 232d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko std::advance(last, 2); 233d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko splice_after(position, src, i, last); 234d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 235d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Splice the element after `i`. 236d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void splice_after(const_iterator position, IntrusiveForwardList&& src, const_iterator i) { 237d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko splice_after(position, src, i); // Use l-value overload. 238d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 239d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Splice elements between `first` and `last`, i.e. open range `(first, last)`. 240d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void splice_after(const_iterator position, 241d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardList& src, 242d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const_iterator first, 243d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const_iterator last) { 244d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko DCHECK(position != end()); 245d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko DCHECK(first != last); 246d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko if (++const_iterator(first) == last) { 247d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Nothing to do. 248d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return; 249d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 250d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // If position is just before end() and last is src.end(), we can finish this quickly. 251d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko if (++const_iterator(position) == end() && last == src.end()) { 252d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko position.hook_->next_hook = first.hook_->next_hook; 253d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko first.hook_->next_hook = nullptr; 254d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return; 255d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 256d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Otherwise we need to find the position before last to fix up the hook. 257d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const_iterator before_last = first; 258d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko while (++const_iterator(before_last) != last) { 259d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko ++before_last; 260d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 261d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Detach (first, last). 262d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const IntrusiveForwardListHook* first_taken = first.hook_->next_hook; 263d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko first.hook_->next_hook = last.hook_; 264d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Attach the sequence to the new position. 265d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko before_last.hook_->next_hook = position.hook_->next_hook; 266d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko position.hook_->next_hook = first_taken; 267d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 268d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Splice elements between `first` and `last`, i.e. open range `(first, last)`. 269d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void splice_after(const_iterator position, 270d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardList&& src, 271d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const_iterator first, 272d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const_iterator last) { 273d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko splice_after(position, src, first, last); // Use l-value overload. 274d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 275d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void remove(const value_type& value) { 276d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko remove_if([value](const value_type& v) { return value == v; }); 277d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 278d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko template <typename Predicate> 279d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void remove_if(Predicate pred) { 280d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko iterator prev = before_begin(); 281d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko for (iterator current = begin(); current != end(); ++current) { 282d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko if (pred(*current)) { 283d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko erase_after(prev); 284d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko current = prev; 285d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } else { 286d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko prev = current; 287d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 288d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 289d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 290d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void unique() { 291d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko unique(std::equal_to<value_type>()); 292d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 293d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko template <typename BinaryPredicate> 294d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void unique(BinaryPredicate pred) { 295d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko if (!empty()) { 296d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko iterator prev = begin(); 297d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko iterator current = prev; 298d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko ++current; 299d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko for (; current != end(); ++current) { 300d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko if (pred(*prev, *current)) { 301d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko erase_after(prev); 302d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko current = prev; 303d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } else { 304d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko prev = current; 305d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 306d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 307d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 308d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 309d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void merge(IntrusiveForwardList& other) { 310d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko merge(other, std::less<value_type>()); 311d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 312d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void merge(IntrusiveForwardList&& other) { 313d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko merge(other); // Use l-value overload. 314d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 315d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko template <typename Compare> 316d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void merge(IntrusiveForwardList& other, Compare cmp) { 317d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko iterator prev = before_begin(); 318d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko iterator current = begin(); 319d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko iterator other_prev = other.before_begin(); 320d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko iterator other_current = other.begin(); 321d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko while (current != end() && other_current != other.end()) { 322d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko if (cmp(*other_current, *current)) { 323d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko ++other_current; 324d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko splice_after(prev, other, other_prev); 325d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko ++prev; 326d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } else { 327d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko prev = current; 328d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko ++current; 329d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 330d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko DCHECK(++const_iterator(prev) == current); 331d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko DCHECK(++const_iterator(other_prev) == other_current); 332d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 333d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko splice_after(prev, other); 334d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 335d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko template <typename Compare> 336d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void merge(IntrusiveForwardList&& other, Compare cmp) { 337d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko merge(other, cmp); // Use l-value overload. 338d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 339d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void sort() { 340d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko sort(std::less<value_type>()); 341d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 342d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko template <typename Compare> 343d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void sort(Compare cmp) { 344d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko size_t n = std::distance(begin(), end()); 345d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko if (n >= 2u) { 346d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const_iterator middle = before_begin(); 347d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko std::advance(middle, n / 2u); 348d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardList second_half; 349d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko second_half.splice_after(second_half.before_begin(), *this, middle, end()); 350d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko sort(cmp); 351d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko second_half.sort(cmp); 352d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko merge(second_half, cmp); 353d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 354d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 355d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko void reverse() { 356d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardList reversed; 357d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko while (!empty()) { 358d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko value_type& value = front(); 359d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko erase_after(before_begin()); 360d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko reversed.insert_after(reversed.before_begin(), value); 361d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 362d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko reversed.swap(*this); 363d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 364d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 365d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko // Extensions. 366d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko bool HasExactlyOneElement() const { 367d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return !empty() && ++begin() == end(); 368d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 369d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko size_t SizeSlow() const { 370d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return std::distance(begin(), end()); 371d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 372d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko bool ContainsNode(const_reference node) const { 373d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko for (auto&& n : *this) { 374d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko if (std::addressof(n) == std::addressof(node)) { 375d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return true; 376d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 377d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 378d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return false; 379d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 380d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 381d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko private: 382d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko static IntrusiveForwardListHook* ModifiableHook(const IntrusiveForwardListHook* hook) { 383d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return const_cast<IntrusiveForwardListHook*>(hook); 384d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 385d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 386d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko IntrusiveForwardListHook first_; 387d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko}; 388d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 389d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markotemplate <typename T, typename HookTraits> 390d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markovoid swap(IntrusiveForwardList<T, HookTraits>& lhs, IntrusiveForwardList<T, HookTraits>& rhs) { 391d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko lhs.swap(rhs); 392d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko} 393d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 394d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markotemplate <typename T, typename HookTraits> 395d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markobool operator==(const IntrusiveForwardList<T, HookTraits>& lhs, 396d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const IntrusiveForwardList<T, HookTraits>& rhs) { 397d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko auto lit = lhs.begin(); 398d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko auto rit = rhs.begin(); 399d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko for (; lit != lhs.end() && rit != rhs.end(); ++lit, ++rit) { 400d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko if (*lit != *rit) { 401d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return false; 402d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 403d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 404d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return lit == lhs.end() && rit == rhs.end(); 405d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko} 406d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 407d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markotemplate <typename T, typename HookTraits> 408d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markobool operator!=(const IntrusiveForwardList<T, HookTraits>& lhs, 409d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const IntrusiveForwardList<T, HookTraits>& rhs) { 410d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return !(lhs == rhs); 411d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko} 412d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 413d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markotemplate <typename T, typename HookTraits> 414d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markobool operator<(const IntrusiveForwardList<T, HookTraits>& lhs, 415d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const IntrusiveForwardList<T, HookTraits>& rhs) { 416d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); 417d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko} 418d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 419d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markotemplate <typename T, typename HookTraits> 420d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markobool operator>(const IntrusiveForwardList<T, HookTraits>& lhs, 421d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const IntrusiveForwardList<T, HookTraits>& rhs) { 422d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return rhs < lhs; 423d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko} 424d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 425d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markotemplate <typename T, typename HookTraits> 426d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markobool operator<=(const IntrusiveForwardList<T, HookTraits>& lhs, 427d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const IntrusiveForwardList<T, HookTraits>& rhs) { 428d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return !(rhs < lhs); 429d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko} 430d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 431d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markotemplate <typename T, typename HookTraits> 432d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markobool operator>=(const IntrusiveForwardList<T, HookTraits>& lhs, 433d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko const IntrusiveForwardList<T, HookTraits>& rhs) { 434d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return !(lhs < rhs); 435d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko} 436d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 437d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markotemplate <typename T, IntrusiveForwardListHook T::* NextPtr> 438d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Markoclass IntrusiveForwardListMemberHook { 439d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko public: 440d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko static const IntrusiveForwardListHook* GetHook(const T* value) { 441d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return &(value->*NextPtr); 442d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 443d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 444d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko static T* GetValue(const IntrusiveForwardListHook* hook) { 445d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko return reinterpret_cast<T*>( 446d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko reinterpret_cast<uintptr_t>(hook) - OFFSETOF_MEMBERPTR(T, NextPtr)); 447d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko } 448d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko}; 449d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 450d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko} // namespace art 451d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko 452d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko#endif // ART_COMPILER_UTILS_INTRUSIVE_FORWARD_LIST_H_ 453