1use crate::Pointer;
56use std::fmt;
57use std::marker::PhantomData;
58use std::mem;
59use std::ptr::null;
60
61pub unsafe trait SListItem<Tag>: Sized {
70 fn get_node(&self) -> &mut SListNode<Self, Tag>;
71}
72
73pub struct SListNode<T: Sized, Tag> {
75 next: *const T,
76 _phan: PhantomData<fn(&Tag)>,
77}
78
79unsafe impl<T, Tag> Send for SListNode<T, Tag> {}
80
81impl<T: SListItem<Tag>, Tag> SListNode<T, Tag> {}
82
83impl<T, Tag> Default for SListNode<T, Tag> {
84 #[inline(always)]
85 fn default() -> Self {
86 Self { next: null(), _phan: Default::default() }
87 }
88}
89
90impl<T: SListItem<Tag> + fmt::Debug, Tag> fmt::Debug for SListNode<T, Tag> {
91 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
92 write!(f, "(")?;
93 if !self.next.is_null() {
94 write!(f, "next: {:p} ", self.next)?;
95 } else {
96 write!(f, "next: none ")?;
97 }
98 write!(f, ")")
99 }
100}
101
102pub struct SLinkedList<P, Tag>
106where
107 P: Pointer,
108 P::Target: SListItem<Tag>,
109{
110 length: u64,
111 head: *const P::Target,
112 tail: *const P::Target,
113 _phan: PhantomData<fn(&Tag)>,
114}
115
116unsafe impl<P, Tag> Send for SLinkedList<P, Tag>
117where
118 P: Pointer,
119 P::Target: SListItem<Tag>,
120{
121}
122
123impl<P: fmt::Debug, Tag> fmt::Debug for SLinkedList<P, Tag>
124where
125 P: Pointer,
126 P::Target: SListItem<Tag>,
127{
128 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
129 write!(f, "{{ length: {} ", self.length)?;
130 if !self.head.is_null() {
131 write!(f, "head: {:?} ", self.head)?;
132 } else {
133 write!(f, "head: none ")?;
134 }
135 if !self.tail.is_null() {
136 write!(f, "tail: {:?} ", self.tail)?;
137 } else {
138 write!(f, "tail: none ")?;
139 }
140 write!(f, "}}")
141 }
142}
143
144impl<P, Tag> SLinkedList<P, Tag>
145where
146 P: Pointer,
147 P::Target: SListItem<Tag>,
148{
149 #[inline(always)]
151 pub fn new() -> Self {
152 SLinkedList { length: 0, head: null(), tail: null(), _phan: Default::default() }
153 }
154
155 #[inline]
158 pub fn clear(&mut self) {
159 self.length = 0;
160 self.head = null();
161 self.tail = null();
162 }
163
164 #[inline(always)]
166 pub fn get_length(&self) -> u64 {
167 return self.length;
168 }
169
170 #[inline(always)]
172 pub fn len(&self) -> usize {
173 return self.length as usize;
174 }
175
176 #[inline(always)]
178 pub fn is_empty(&self) -> bool {
179 self.length == 0
180 }
181
182 #[inline]
184 pub fn push_back(&mut self, item: P) {
185 let node = item.as_ref().get_node();
186 node.next = null();
187
188 let ptr = item.into_raw();
189
190 if self.tail.is_null() {
191 self.head = ptr;
193 } else {
194 unsafe {
196 (*self.tail).get_node().next = ptr;
197 }
198 }
199 self.tail = ptr;
200 self.length += 1;
201 }
202
203 pub fn pop_front(&mut self) -> Option<P> {
205 if self.head.is_null() {
206 None
207 } else {
208 let head_ptr = self.head;
209 let node = unsafe { (*head_ptr).get_node() };
210 let next_ptr = node.next;
211
212 self.head = next_ptr;
214
215 if self.head.is_null() {
217 self.tail = null();
218 }
219
220 node.next = null();
222 self.length -= 1;
223
224 Some(unsafe { P::from_raw(head_ptr) })
225 }
226 }
227
228 #[inline]
230 pub fn get_front(&self) -> Option<&P::Target> {
231 if self.head.is_null() { None } else { unsafe { Some(&(*self.head)) } }
232 }
233
234 #[inline]
236 pub fn get_back(&self) -> Option<&P::Target> {
237 if self.tail.is_null() { None } else { unsafe { Some(&(*self.tail)) } }
238 }
239
240 #[inline(always)]
242 pub fn is_front(&self, node: &P::Target) -> bool {
243 if self.head.is_null() { false } else { self.head == node as *const P::Target }
244 }
245
246 #[inline(always)]
249 pub fn iter<'a>(&'a self) -> SLinkedListIterator<'a, P, Tag> {
250 SLinkedListIterator { list: self, cur: null() }
251 }
252
253 #[inline(always)]
255 pub fn drain<'a>(&'a mut self) -> SLinkedListDrainer<'a, P, Tag> {
256 SLinkedListDrainer { list: self }
257 }
258}
259
260impl<P, Tag> Drop for SLinkedList<P, Tag>
261where
262 P: Pointer,
263 P::Target: SListItem<Tag>,
264{
265 fn drop(&mut self) {
266 if mem::needs_drop::<P>() {
267 self.drain().for_each(drop);
268 }
269 }
270}
271
272pub struct SLinkedListIterator<'a, P, Tag>
273where
274 P: Pointer,
275 P::Target: SListItem<Tag>,
276{
277 list: &'a SLinkedList<P, Tag>,
278 cur: *const P::Target,
279}
280
281unsafe impl<'a, P, Tag> Send for SLinkedListIterator<'a, P, Tag>
282where
283 P: Pointer,
284 P::Target: SListItem<Tag>,
285{
286}
287
288impl<'a, P, Tag> Iterator for SLinkedListIterator<'a, P, Tag>
289where
290 P: Pointer,
291 P::Target: SListItem<Tag>,
292{
293 type Item = &'a P::Target;
294
295 fn next(&mut self) -> Option<Self::Item> {
296 if self.cur.is_null() {
297 if self.list.head.is_null() {
298 return None;
299 } else {
300 self.cur = self.list.head;
301 }
302 } else {
303 let next = unsafe { (*self.cur).get_node().next };
304 if next.is_null() {
305 return None;
306 } else {
307 self.cur = next;
308 }
309 }
310 unsafe { Some(&(*self.cur)) }
311 }
312}
313
314pub struct SLinkedListDrainer<'a, P, Tag>
315where
316 P: Pointer,
317 P::Target: SListItem<Tag>,
318{
319 list: &'a mut SLinkedList<P, Tag>,
320}
321
322unsafe impl<'a, P, Tag> Send for SLinkedListDrainer<'a, P, Tag>
323where
324 P: Pointer,
325 P::Target: SListItem<Tag>,
326{
327}
328
329impl<'a, P, Tag> Iterator for SLinkedListDrainer<'a, P, Tag>
330where
331 P: Pointer,
332 P::Target: SListItem<Tag>,
333{
334 type Item = P;
335
336 #[inline]
337 fn next(&mut self) -> Option<P> {
338 self.list.pop_front()
339 }
340}
341
342#[cfg(test)]
343mod tests {
344 use super::*;
345 use std::cell::UnsafeCell;
346 use std::sync::atomic::{AtomicUsize, Ordering};
347
348 pub struct TestTag;
349
350 #[derive(Debug)]
351 pub struct TestNode {
352 pub value: i64,
353 pub node: UnsafeCell<SListNode<Self, TestTag>>,
354 pub drop_detector: usize,
355 }
356
357 static NEXT_DROP_ID: AtomicUsize = AtomicUsize::new(0);
358 static ACTIVE_NODE_COUNT: AtomicUsize = AtomicUsize::new(0);
359
360 impl Drop for TestNode {
361 fn drop(&mut self) {
362 ACTIVE_NODE_COUNT.fetch_sub(1, Ordering::SeqCst);
363 }
364 }
365
366 unsafe impl Send for TestNode {}
367
368 unsafe impl SListItem<TestTag> for TestNode {
369 fn get_node(&self) -> &mut SListNode<Self, TestTag> {
370 unsafe { &mut *self.node.get() }
371 }
372 }
373
374 fn new_node(v: i64) -> TestNode {
375 ACTIVE_NODE_COUNT.fetch_add(1, Ordering::SeqCst);
376 TestNode {
377 value: v,
378 node: UnsafeCell::new(SListNode::default()),
379 drop_detector: NEXT_DROP_ID.fetch_add(1, Ordering::SeqCst),
380 }
381 }
382
383 #[test]
384 fn test_push_back_pop_front_box() {
385 ACTIVE_NODE_COUNT.store(0, Ordering::SeqCst);
386 let mut l = SLinkedList::<Box<TestNode>, TestTag>::new();
387
388 let node1 = Box::new(new_node(1));
389 l.push_back(node1);
390
391 let node2 = Box::new(new_node(2));
392 l.push_back(node2);
393
394 let node3 = Box::new(new_node(3));
395 l.push_back(node3);
396
397 assert_eq!(3, l.get_length());
398 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 3);
399
400 let mut iter = l.iter();
402 assert_eq!(iter.next().unwrap().value, 1);
403 assert_eq!(iter.next().unwrap().value, 2);
404 assert_eq!(iter.next().unwrap().value, 3);
405 assert!(iter.next().is_none());
406
407 let n1 = l.pop_front();
409 assert!(n1.is_some());
410 assert_eq!(n1.unwrap().value, 1);
411 assert_eq!(l.get_length(), 2);
412
413 let n2 = l.pop_front();
414 assert!(n2.is_some());
415 assert_eq!(n2.unwrap().value, 2);
416 assert_eq!(l.get_length(), 1);
417
418 let n3 = l.pop_front();
419 assert!(n3.is_some());
420 assert_eq!(n3.unwrap().value, 3);
421 assert_eq!(l.get_length(), 0);
422
423 assert!(l.pop_front().is_none());
424 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 0);
425 }
426
427 #[test]
428 fn test_drain() {
429 ACTIVE_NODE_COUNT.store(0, Ordering::SeqCst);
430 let mut l = SLinkedList::<Box<TestNode>, TestTag>::new();
431
432 l.push_back(Box::new(new_node(10)));
433 l.push_back(Box::new(new_node(20)));
434 l.push_back(Box::new(new_node(30)));
435
436 assert_eq!(l.get_length(), 3);
437 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 3);
438
439 {
440 let mut drain = l.drain();
441 assert_eq!(drain.next().unwrap().value, 10);
442 assert_eq!(drain.next().unwrap().value, 20);
443 assert_eq!(drain.next().unwrap().value, 30);
444 assert!(drain.next().is_none());
445 }
446
447 assert_eq!(l.get_length(), 0);
448 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 0);
449 }
450}