1use crate::{chunk::Chunk, *};
2use std::{alloc::Layout, collections::VecDeque};
3
4pub struct PinnedDeque<T: Sized> {
5 size: usize,
6 cap_per_chunk: u32,
7 layout: Layout,
8 pub(crate) used: VecDeque<*mut Chunk<T>>,
9 freed: Vec<*mut Chunk<T>>,
10}
11
12impl<T> PinnedDeque<T>
13where
14 T: Sized,
15{
16 pub fn new() -> Self {
23 let cap_per_chunk = Chunk::<T>::capacity_per_chunk();
24 let layout = Chunk::<T>::layout(cap_per_chunk);
25 Self {
26 size: 0,
27 cap_per_chunk,
28 layout,
29 used: VecDeque::new(),
30 freed: Vec::new(),
31 }
32 }
33
34 pub fn with_capacity_per_chunk(cap_per_chunk: u32) -> Self {
36 let layout = Chunk::<T>::layout(cap_per_chunk);
37 Self {
38 size: 0,
39 cap_per_chunk,
40 layout,
41 used: VecDeque::new(),
42 freed: Vec::new(),
43 }
44 }
45
46 pub fn reserve(&mut self, additional: usize) {
48 let cap_per_chunk = self.cap_per_chunk as usize;
49 let n = additional.div_ceil(cap_per_chunk);
50 if n > self.freed.len() {
51 for _ in self.freed.len()..n {
52 self.freed.push(Chunk::<T>::new(self.layout));
53 }
54 }
55 debug_assert!(n <= self.freed.len());
56 }
57
58 pub fn len(&self) -> usize {
59 self.size
60 }
61
62 pub fn is_empty(&self) -> bool {
63 self.len() == 0
64 }
65
66 pub fn capacity(&self) -> usize {
71 (self.used.len() + self.freed.len()) * (self.cap_per_chunk as usize)
72 }
73
74 pub fn push_back(&mut self, elem: T) {
75 self.size += 1;
76 if let Some(back_chunk) = self.used.back() {
77 let back_chunk = unsafe { &mut **back_chunk };
78 if let Some(slot) = back_chunk.reserve_back(self.cap_per_chunk) {
79 slot.write(elem);
80 return;
81 }
82 }
83 let new_chunk = self.fetch_a_freed_chunk();
84 unsafe {
85 let new_chunk = &mut *new_chunk;
86 new_chunk.reset_for_back_insertion();
87 new_chunk
88 .reserve_back(self.cap_per_chunk)
89 .unwrap_unchecked()
90 .write(elem);
91 }
92 self.used.push_back(new_chunk);
93 }
94
95 pub fn push_front(&mut self, elem: T) {
96 self.size += 1;
97 if let Some(front_chunk) = self.used.front() {
98 let front_chunk = unsafe { &mut **front_chunk };
99 if let Some(slot) = front_chunk.reserve_front() {
100 slot.write(elem);
101 return;
102 }
103 }
104 let new_chunk = self.fetch_a_freed_chunk();
105 unsafe {
106 let new_chunk = &mut *new_chunk;
107 new_chunk.reset_for_front_insertion(self.cap_per_chunk);
108 new_chunk.reserve_front().unwrap_unchecked().write(elem);
109 }
110 self.used.push_front(new_chunk);
111 }
112
113 pub fn pop_back(&mut self) -> Option<T> {
114 if let Some(back_chunk) = self.used.back() {
115 let back_chunk = unsafe { &mut **back_chunk };
116 let res = back_chunk.pop_back();
117 if back_chunk.len() == 0 {
118 let last_chunk = unsafe { self.used.pop_back().unwrap_unchecked() };
119 self.recycle(last_chunk);
120 }
121 self.size -= 1;
122 Some(res)
123 } else {
124 None
125 }
126 }
127
128 pub fn pop_front(&mut self) -> Option<T> {
129 if let Some(front_chunk) = self.used.front() {
130 let front_chunk = unsafe { &mut **front_chunk };
131 let res = front_chunk.pop_front();
132 if front_chunk.len() == 0 {
133 let first_chunk = unsafe { self.used.pop_front().unwrap_unchecked() };
134 self.recycle(first_chunk);
135 }
136 self.size -= 1;
137 Some(res)
138 } else {
139 None
140 }
141 }
142
143 pub fn back(&self) -> Option<&T> {
144 self.used.back().map(|back_chunk| {
145 let back_chunk = unsafe { &*(*back_chunk as *const Chunk<T>) };
146 back_chunk.back()
147 })
148 }
149
150 pub fn front(&self) -> Option<&T> {
151 self.used.front().map(|front_chunk| {
152 let front_chunk = unsafe { &*(*front_chunk as *const Chunk<T>) };
153 front_chunk.front()
154 })
155 }
156
157 pub fn back_mut(&mut self) -> Option<&mut T> {
158 self.used.back().map(|back_chunk| {
159 let back_chunk = unsafe { &mut **back_chunk };
160 back_chunk.back_mut()
161 })
162 }
163
164 pub fn front_mut(&mut self) -> Option<&mut T> {
165 self.used.front().map(|front_chunk| {
166 let front_chunk = unsafe { &mut **front_chunk };
167 front_chunk.front_mut()
168 })
169 }
170
171 pub fn clear(&mut self) {
172 while let Some(chunk_ptr) = self.used.pop_front() {
173 let chunk = unsafe { &mut *chunk_ptr };
174 chunk.drop_all();
175 self.recycle(chunk_ptr);
176 }
177 }
178
179 pub fn get(&self, mut idx: usize) -> Option<&T> {
180 if idx >= self.len() {
181 return None;
182 }
183 let first_chunk = unsafe { &*(*self.used.front().unwrap_unchecked() as *const Chunk<T>) };
184 if idx < first_chunk.len() {
185 return Some(first_chunk.get(idx));
186 } else {
187 idx -= first_chunk.len();
188 }
189 let n = idx / (self.cap_per_chunk as usize);
190 let offset = idx % (self.cap_per_chunk as usize);
191 let target_chunk = unsafe { &*(self.used[n + 1] as *const Chunk<T>) };
192 Some(target_chunk.get(offset))
193 }
194
195 pub fn get_mut(&mut self, mut idx: usize) -> Option<&mut T> {
196 if idx >= self.len() {
197 return None;
198 }
199 let front_chunk = unsafe { &mut **self.used.front().unwrap_unchecked() };
200 if idx < front_chunk.len() {
201 return Some(front_chunk.get_mut(idx));
202 } else {
203 idx -= front_chunk.len();
204 }
205 let n = idx / (self.cap_per_chunk as usize);
206 let offset = idx % (self.cap_per_chunk as usize);
207 let target_chunk = unsafe { &mut *self.used[n + 1] };
208 Some(target_chunk.get_mut(offset))
209 }
210
211 pub fn iter(&self) -> Iter<'_, T> {
212 Iter::new(self)
213 }
214
215 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
216 IterMut::new(self)
217 }
218
219 fn fetch_a_freed_chunk(&mut self) -> *mut Chunk<T> {
220 if let Some(chunk) = self.freed.pop() {
221 chunk
222 } else {
223 Chunk::<T>::new(self.layout)
224 }
225 }
226
227 fn recycle(&mut self, chunk: *mut Chunk<T>) {
228 self.freed.push(chunk);
229 }
230}
231
232impl<T> Drop for PinnedDeque<T>
233where
234 T: Sized,
235{
236 fn drop(&mut self) {
237 self.clear();
238 while let Some(chunk) = self.freed.pop() {
239 Chunk::<T>::free(chunk, self.layout);
240 }
241 }
242}