1#![allow(rustdoc::redundant_explicit_links)]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![cfg_attr(docsrs, allow(unused_attributes))]
4#![cfg_attr(not(feature = "std"), no_std)]
5
6extern crate alloc;
90#[cfg(any(feature = "std", test))]
91extern crate std;
92
93use core::fmt;
94use core::marker::PhantomData;
95use core::mem;
96use core::ptr::{self, null};
97use pointers::Pointer;
98
99pub unsafe trait SListItem<Tag>: Sized {
109 fn get_node(&self) -> &mut SListNode<Self, Tag>;
110}
111
112#[repr(C)]
115pub struct SListNode<T: Sized, Tag> {
116 next: *const T,
117 _phan: PhantomData<fn(&Tag)>,
118}
119
120unsafe impl<T, Tag> Send for SListNode<T, Tag> {}
121
122impl<T: SListItem<Tag>, Tag> SListNode<T, Tag> {}
123
124impl<T, Tag> Default for SListNode<T, Tag> {
125 #[inline(always)]
126 fn default() -> Self {
127 Self { next: null(), _phan: Default::default() }
128 }
129}
130
131impl<T: SListItem<Tag> + fmt::Debug, Tag> fmt::Debug for SListNode<T, Tag> {
132 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
133 write!(f, "(")?;
134 if !self.next.is_null() {
135 write!(f, "next: {:p} ", self.next)?;
136 } else {
137 write!(f, "next: none ")?;
138 }
139 write!(f, ")")
140 }
141}
142
143#[repr(C)]
147pub struct SLinkedList<P, Tag>
148where
149 P: Pointer,
150 P::Target: SListItem<Tag>,
151{
152 length: usize,
153 head: *const P::Target,
154 tail: *const P::Target,
155 _phan: PhantomData<fn(&Tag)>,
156}
157
158unsafe impl<P, Tag> Send for SLinkedList<P, Tag>
159where
160 P: Pointer,
161 P::Target: SListItem<Tag>,
162{
163}
164
165impl<P: fmt::Debug, Tag> fmt::Debug for SLinkedList<P, Tag>
166where
167 P: Pointer,
168 P::Target: SListItem<Tag>,
169{
170 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171 write!(f, "{{ length: {} ", self.length)?;
172 if !self.head.is_null() {
173 write!(f, "head: {:?} ", self.head)?;
174 } else {
175 write!(f, "head: none ")?;
176 }
177 if !self.tail.is_null() {
178 write!(f, "tail: {:?} ", self.tail)?;
179 } else {
180 write!(f, "tail: none ")?;
181 }
182 write!(f, "}}")
183 }
184}
185
186impl<P, Tag> SLinkedList<P, Tag>
187where
188 P: Pointer,
189 P::Target: SListItem<Tag>,
190{
191 #[inline(always)]
193 pub fn new() -> Self {
194 SLinkedList { length: 0, head: null(), tail: null(), _phan: Default::default() }
195 }
196
197 #[inline]
199 pub fn clear(&mut self) {
200 while self.pop_front().is_some() {}
204 }
205
206 #[inline(always)]
208 pub fn len(&self) -> usize {
209 self.length
210 }
211
212 #[inline(always)]
214 pub fn is_empty(&self) -> bool {
215 self.length == 0
216 }
217
218 #[inline]
220 pub fn push_back(&mut self, item: P) {
221 let node = item.as_ref().get_node();
222 node.next = null();
223 let ptr = item.into_raw();
224 if !self.tail.is_null() {
225 unsafe {
227 (*self.tail).get_node().next = ptr;
228 }
229 } else {
230 self.head = ptr;
232 }
233 self.tail = ptr;
234 self.length += 1;
235 }
236
237 #[inline]
239 pub fn push_front(&mut self, item: P) {
240 let ptr = item.into_raw();
241 let node = unsafe { (*ptr).get_node() };
242 node.next = self.head;
243 if self.head.is_null() {
244 self.tail = ptr;
246 }
247 self.head = ptr;
248 self.length += 1;
249 }
250
251 pub fn pop_front(&mut self) -> Option<P> {
253 if !self.head.is_null() {
254 let head_ptr = self.head;
255 let node = unsafe { (*head_ptr).get_node() };
256 let next_ptr = node.next;
257
258 self.head = next_ptr;
260
261 if self.head.is_null() {
263 self.tail = null();
264 }
265
266 node.next = null();
268 self.length -= 1;
269
270 Some(unsafe { P::from_raw(head_ptr) })
271 } else {
272 None
273 }
274 }
275
276 #[inline]
278 pub fn get_front(&self) -> Option<&P::Target> {
279 if !self.head.is_null() { unsafe { Some(&(*self.head)) } } else { None }
280 }
281
282 #[inline]
284 pub fn get_back(&self) -> Option<&P::Target> {
285 if !self.tail.is_null() { unsafe { Some(&(*self.tail)) } } else { None }
286 }
287
288 #[inline(always)]
290 pub fn is_front(&self, node: &P::Target) -> bool {
291 if self.head.is_null() { false } else { ptr::eq(self.head, node) }
292 }
293
294 #[inline(always)]
306 pub fn iter<'a>(&'a self) -> SLinkedListIterator<'a, P, Tag> {
307 SLinkedListIterator { list: self, cur: null() }
308 }
309
310 #[inline(always)]
312 pub fn drain<'a>(&'a mut self) -> SLinkedListDrainer<'a, P, Tag> {
313 SLinkedListDrainer { list: self }
314 }
315}
316
317impl<P, Tag> Drop for SLinkedList<P, Tag>
318where
319 P: Pointer,
320 P::Target: SListItem<Tag>,
321{
322 fn drop(&mut self) {
323 if mem::needs_drop::<P>() {
324 self.drain().for_each(drop);
325 }
326 }
327}
328
329pub struct SLinkedListIterator<'a, P, Tag>
330where
331 P: Pointer,
332 P::Target: SListItem<Tag>,
333{
334 list: &'a SLinkedList<P, Tag>,
335 cur: *const P::Target,
336}
337
338unsafe impl<'a, P, Tag> Send for SLinkedListIterator<'a, P, Tag>
339where
340 P: Pointer,
341 P::Target: SListItem<Tag>,
342{
343}
344
345impl<'a, P, Tag> Iterator for SLinkedListIterator<'a, P, Tag>
346where
347 P: Pointer,
348 P::Target: SListItem<Tag>,
349{
350 type Item = &'a P::Target;
351
352 #[inline]
353 fn next(&mut self) -> Option<Self::Item> {
354 if !self.cur.is_null() {
355 let next = unsafe { (*self.cur).get_node().next };
356 if !next.is_null() {
357 self.cur = next;
358 } else {
359 return None;
360 }
361 } else {
362 if !self.list.head.is_null() {
363 self.cur = self.list.head;
364 } else {
365 return None;
366 }
367 }
368 unsafe { Some(&(*self.cur)) }
369 }
370}
371
372pub struct SLinkedListDrainer<'a, P, Tag>
373where
374 P: Pointer,
375 P::Target: SListItem<Tag>,
376{
377 list: &'a mut SLinkedList<P, Tag>,
378}
379
380unsafe impl<'a, P, Tag> Send for SLinkedListDrainer<'a, P, Tag>
381where
382 P: Pointer,
383 P::Target: SListItem<Tag>,
384{
385}
386
387impl<'a, P, Tag> Iterator for SLinkedListDrainer<'a, P, Tag>
388where
389 P: Pointer,
390 P::Target: SListItem<Tag>,
391{
392 type Item = P;
393
394 #[inline]
395 fn next(&mut self) -> Option<P> {
396 self.list.pop_front()
397 }
398}
399
400#[cfg(test)]
401mod tests {
402 use super::*;
403 use alloc::boxed::Box;
404 use std::cell::UnsafeCell;
405 use std::sync::atomic::{AtomicUsize, Ordering};
406
407 pub struct TestTag;
408
409 #[derive(Debug)]
410 pub struct TestNode {
411 pub value: i64,
412 pub node: UnsafeCell<SListNode<Self, TestTag>>,
413 }
414
415 static ACTIVE_NODE_COUNT: AtomicUsize = AtomicUsize::new(0);
416
417 impl Drop for TestNode {
418 fn drop(&mut self) {
419 ACTIVE_NODE_COUNT.fetch_sub(1, Ordering::SeqCst);
420 }
421 }
422
423 unsafe impl Send for TestNode {}
424
425 unsafe impl SListItem<TestTag> for TestNode {
426 fn get_node(&self) -> &mut SListNode<Self, TestTag> {
427 unsafe { &mut *self.node.get() }
428 }
429 }
430
431 fn new_node(v: i64) -> TestNode {
432 ACTIVE_NODE_COUNT.fetch_add(1, Ordering::SeqCst);
433 TestNode { value: v, node: UnsafeCell::new(SListNode::default()) }
434 }
435
436 #[test]
437 fn test_push_back_pop_front_box() {
438 ACTIVE_NODE_COUNT.store(0, Ordering::SeqCst);
439 let mut l = SLinkedList::<Box<TestNode>, TestTag>::new();
440
441 let node1 = Box::new(new_node(1));
442 l.push_back(node1);
443
444 let node2 = Box::new(new_node(2));
445 l.push_back(node2);
446
447 let node3 = Box::new(new_node(3));
448 l.push_back(node3);
449
450 assert_eq!(3, l.len());
451 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 3);
452
453 let mut iter = l.iter();
455 assert_eq!(iter.next().unwrap().value, 1);
456 assert_eq!(iter.next().unwrap().value, 2);
457 assert_eq!(iter.next().unwrap().value, 3);
458 assert!(iter.next().is_none());
459
460 let n1 = l.pop_front();
462 assert!(n1.is_some());
463 assert_eq!(n1.unwrap().value, 1);
464 assert_eq!(l.len(), 2);
465
466 let n2 = l.pop_front();
467 assert!(n2.is_some());
468 assert_eq!(n2.unwrap().value, 2);
469 assert_eq!(l.len(), 1);
470
471 let n3 = l.pop_front();
472 assert!(n3.is_some());
473 assert_eq!(n3.unwrap().value, 3);
474 assert_eq!(l.len(), 0);
475
476 assert!(l.pop_front().is_none());
477 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 0);
478 }
479
480 #[test]
481 fn test_push_front_box() {
482 ACTIVE_NODE_COUNT.store(0, Ordering::SeqCst);
483 let mut l = SLinkedList::<Box<TestNode>, TestTag>::new();
484
485 let node1 = Box::new(new_node(1));
486 l.push_front(node1); let node2 = Box::new(new_node(2));
489 l.push_front(node2); let node3 = Box::new(new_node(3));
492 l.push_front(node3); assert_eq!(3, l.len());
495 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 3);
496
497 let mut iter = l.iter();
499 assert_eq!(iter.next().unwrap().value, 3);
500 assert_eq!(iter.next().unwrap().value, 2);
501 assert_eq!(iter.next().unwrap().value, 1);
502 assert!(iter.next().is_none());
503
504 let n1 = l.pop_front();
506 assert!(n1.is_some());
507 assert_eq!(n1.unwrap().value, 3);
508 assert_eq!(l.len(), 2);
509
510 let n2 = l.pop_front();
511 assert!(n2.is_some());
512 assert_eq!(n2.unwrap().value, 2);
513 assert_eq!(l.len(), 1);
514
515 let n3 = l.pop_front();
516 assert!(n3.is_some());
517 assert_eq!(n3.unwrap().value, 1);
518 assert_eq!(l.len(), 0);
519
520 assert!(l.pop_front().is_none());
521 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 0);
522 }
523
524 #[test]
525 fn test_drain() {
526 ACTIVE_NODE_COUNT.store(0, Ordering::SeqCst);
527 let mut l = SLinkedList::<Box<TestNode>, TestTag>::new();
528
529 l.push_back(Box::new(new_node(10)));
530 l.push_back(Box::new(new_node(20)));
531 l.push_back(Box::new(new_node(30)));
532
533 assert_eq!(l.len(), 3);
534 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 3);
535
536 {
537 let mut drain = l.drain();
538 assert_eq!(drain.next().unwrap().value, 10);
539 assert_eq!(drain.next().unwrap().value, 20);
540 assert_eq!(drain.next().unwrap().value, 30);
541 assert!(drain.next().is_none());
542 }
543
544 assert_eq!(l.len(), 0);
545 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 0);
546 }
547
548 #[test]
549 fn test_clear() {
550 ACTIVE_NODE_COUNT.store(0, Ordering::SeqCst);
551 let mut l = SLinkedList::<Box<TestNode>, TestTag>::new();
552
553 l.push_back(Box::new(new_node(1)));
554 l.push_back(Box::new(new_node(2)));
555 assert_eq!(l.len(), 2);
556 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 2);
557
558 l.clear();
559
560 assert!(l.is_empty());
561 assert_eq!(l.len(), 0);
562 assert!(l.get_front().is_none());
563 assert!(l.get_back().is_none());
564 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 0);
565
566 l.push_back(Box::new(new_node(3)));
568 assert_eq!(l.len(), 1);
569 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 1);
570 }
571}