C/C++ API Reference
Loading...
Searching...
No Matches
intrusive_queue.h
1// Copyright 2026 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include <initializer_list>
17#include <iterator>
18#include <type_traits>
19#include <utility>
20
21#include "pw_containers/internal/intrusive_queue.h"
22#include "pw_containers/intrusive_forward_list.h"
23
24namespace pw {
25
29template <typename T>
31 private:
32 using ItemBase = containers::internal::IntrusiveQueueItem;
33
34 public:
35 class Item : public ItemBase {
36 protected:
37 constexpr explicit Item() = default;
38
39 private:
40 template <typename, typename, bool>
41 friend struct containers::internal::IntrusiveItem;
42 using ItemType = T;
43 };
44
45 using element_type = T;
46 using value_type = std::remove_cv_t<element_type>;
47 using size_type = std::size_t;
48 using difference_type = std::ptrdiff_t;
49 using reference = value_type&;
50 using const_reference = const value_type&;
51 using pointer = element_type*;
52 using const_pointer = const element_type*;
53
54 using iterator = typename containers::internal::ForwardIterator<T, ItemBase>;
55 using const_iterator =
56 typename containers::internal::ForwardIterator<std::add_const_t<T>,
57 const ItemBase>;
58
59 constexpr IntrusiveQueue() = default;
60
61 // Intrusive queues cannot be copied.
62 IntrusiveQueue(const IntrusiveQueue&) = delete;
63 IntrusiveQueue& operator=(const IntrusiveQueue&) = delete;
64
67
70
72 template <typename Iterator>
73 IntrusiveQueue(Iterator first, Iterator last) {
74 assign(first, last);
75 }
76
78 IntrusiveQueue(std::initializer_list<T*> items) {
79 assign(items.begin(), items.end());
80 }
81
82 template <typename Iterator>
83 void assign(Iterator first, Iterator last) {
84 CheckItemType();
85 generic_queue_.assign(first, last);
86 }
87
88 void assign(std::initializer_list<T*> items) {
89 assign(items.begin(), items.end());
90 }
91
92 // Iterators
93
94 iterator before_begin() noexcept {
95 return iterator(generic_queue_.before_begin());
96 }
97 const_iterator before_begin() const noexcept {
98 return const_iterator(generic_queue_.before_begin());
99 }
100 const_iterator cbefore_begin() const noexcept { return before_begin(); }
101
102 iterator begin() noexcept { return iterator(generic_queue_.begin()); }
103 const_iterator begin() const noexcept {
104 return const_iterator(generic_queue_.begin());
105 }
106 const_iterator cbegin() const noexcept { return begin(); }
107
108 iterator end() noexcept { return iterator(generic_queue_.end()); }
109 const_iterator end() const noexcept {
110 return const_iterator(generic_queue_.end());
111 }
112 const_iterator cend() const noexcept { return end(); }
113
114 // Element access
115
116 reference front() { return *static_cast<T*>(generic_queue_.begin()); }
117 const_reference front() const {
118 return *static_cast<const T*>(generic_queue_.begin());
119 }
120
121 reference back() { return *static_cast<T*>(generic_queue_.tail()); }
122 const_reference back() const {
123 return *static_cast<const T*>(generic_queue_.tail());
124 }
125
126 // Capacity
127
128 [[nodiscard]] bool empty() const noexcept { return generic_queue_.empty(); }
129 constexpr size_type max_size() const noexcept {
130 return std::numeric_limits<difference_type>::max();
131 }
132
133 // Modifiers
134
135 void clear() { generic_queue_.clear(); }
136
138 void push_front(T& item) { generic_queue_.push_front(item); }
139
141 void pop_front() { generic_queue_.pop_front(); }
142
144 void push_back(T& item) { generic_queue_.push_back(item); }
145
147 iterator insert_after(iterator pos, T& item) {
148 return iterator(generic_queue_.insert_after(pos.item_, item));
149 }
150
152 template <typename Iterator>
153 iterator insert_after(iterator pos, Iterator first, Iterator last) {
154 return iterator(generic_queue_.insert_after(pos.item_, first, last));
155 }
156
158 iterator insert_after(iterator pos, std::initializer_list<T*> items) {
159 return insert_after(pos, items.begin(), items.end());
160 }
161
163 iterator erase_after(iterator pos) {
164 return iterator(generic_queue_.erase_after(pos.item_));
165 }
166
168 iterator erase_after(iterator first, iterator last) {
169 return iterator(generic_queue_.erase_after(first.item_, last.item_));
170 }
171
175 bool remove(const T& item_to_remove) {
176 return generic_queue_.remove(item_to_remove);
177 }
178
180 template <typename UnaryPredicate>
181 size_type remove_if(UnaryPredicate&& pred) {
182 return generic_queue_.remove_if<T>(std::forward<UnaryPredicate>(pred));
183 }
184
185 void swap(IntrusiveQueue<T>& other) noexcept {
186 generic_queue_.swap(other.generic_queue_);
187 }
188
189 private:
190 // Check that T is an Item in a function, since the class T will not be fully
191 // defined when the IntrusiveQueue<T> class is instantiated.
192 static constexpr void CheckItemType() {
193 using IntrusiveItemType =
194 typename containers::internal::IntrusiveItem<ItemBase, T>::Type;
195 static_assert(
196 std::is_base_of_v<IntrusiveItemType, T>,
197 "IntrusiveQueue items must be derived from IntrusiveQueue<T>::Item, "
198 "where T is the item or one of its bases.");
199 }
200
201 containers::internal::GenericIntrusiveQueue generic_queue_;
202};
203
204} // namespace pw
Definition: intrusive_queue.h:35
Definition: intrusive_queue.h:30
void push_back(T &item)
Inserts an element at the end of the queue in O(1) time.
Definition: intrusive_queue.h:144
iterator insert_after(iterator pos, std::initializer_list< T * > items)
Inserts an initializer list after the specified pos.
Definition: intrusive_queue.h:158
IntrusiveQueue(IntrusiveQueue &&)=default
Moves the other queue's contents into this queue.
IntrusiveQueue(std::initializer_list< T * > items)
Constructs a queue from a std::initializer_list of pointers to items.
Definition: intrusive_queue.h:78
IntrusiveQueue(Iterator first, Iterator last)
Constructs a queue from an iterator over items.
Definition: intrusive_queue.h:73
void push_front(T &item)
Inserts an element at the beginning of the queue.
Definition: intrusive_queue.h:138
void pop_front()
Removes the first element of the queue.
Definition: intrusive_queue.h:141
size_type remove_if(UnaryPredicate &&pred)
Removes any item for which the given unary predicate evaluates to true.
Definition: intrusive_queue.h:181
iterator erase_after(iterator first, iterator last)
Removes a range of items.
Definition: intrusive_queue.h:168
iterator insert_after(iterator pos, T &item)
Inserts item after the specified pos.
Definition: intrusive_queue.h:147
iterator insert_after(iterator pos, Iterator first, Iterator last)
Inserts a range after the specified pos.
Definition: intrusive_queue.h:153
iterator erase_after(iterator pos)
Removes the item succeeding pos.
Definition: intrusive_queue.h:163
bool remove(const T &item_to_remove)
Definition: intrusive_queue.h:175
IntrusiveQueue & operator=(IntrusiveQueue &&)=default
Clears this queue and moves the other queue's contents into it.
The Pigweed namespace.
Definition: alignment.h:27