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