1use crate::ptr_traits::{ManagedPtr, PtrTraits};
6use crate::sentinel::{is_sentinel_ptr, make_sentinel};
7use crate::size_tracker::{NonTrackingSize, SizeTracker, TrackingSize};
8use crate::tag::DefaultObjectTag;
9use core::cell::UnsafeCell;
10use core::pin::Pin;
11use pin_init::{PinInit, pin_data, pin_init, pinned_drop};
12
13#[repr(C)]
15pub struct DoublyLinkedListNode<T> {
16 pub next: UnsafeCell<*mut T>,
18 pub prev: UnsafeCell<*mut T>,
20}
21
22impl<T> DoublyLinkedListNode<T> {
23 pub const fn new() -> Self {
25 Self {
26 next: UnsafeCell::new(core::ptr::null_mut()),
27 prev: UnsafeCell::new(core::ptr::null_mut()),
28 }
29 }
30
31 pub fn in_container(&self) -> bool {
33 !unsafe { *self.next.get() }.is_null()
36 }
37
38 fn get_next(&self) -> *mut T {
39 unsafe { *self.next.get() }
41 }
42
43 fn set_next(&self, next: *mut T) {
44 unsafe {
47 *self.next.get() = next;
48 }
49 }
50
51 fn get_prev(&self) -> *mut T {
52 unsafe { *self.prev.get() }
54 }
55
56 fn set_prev(&self, prev: *mut T) {
57 unsafe {
60 *self.prev.get() = prev;
61 }
62 }
63}
64
65impl<T> core::fmt::Debug for DoublyLinkedListNode<T> {
66 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
67 f.debug_struct("DoublyLinkedListNode").field("in_container", &self.in_container()).finish()
68 }
69}
70
71impl<T> Default for DoublyLinkedListNode<T> {
72 fn default() -> Self {
73 Self::new()
74 }
75}
76
77::zr::static_assert!(
79 core::mem::size_of::<DoublyLinkedListNode<()>>() == 2 * core::mem::size_of::<*mut ()>()
80);
81::zr::static_assert!(
82 core::mem::align_of::<DoublyLinkedListNode<()>>() == core::mem::align_of::<*mut ()>()
83);
84
85impl<T> Drop for DoublyLinkedListNode<T> {
86 fn drop(&mut self) {
87 debug_assert!(!self.in_container(), "Object destroyed while still in container");
88 }
89}
90
91pub trait DoublyLinkedListContainable<T, Tag = DefaultObjectTag> {
93 fn get_node(&self) -> &DoublyLinkedListNode<T>;
95}
96
97#[repr(C)]
249#[pin_data(PinnedDrop)]
250pub struct DoublyLinkedList<P, Tag = DefaultObjectTag, S = NonTrackingSize>
251where
252 P: PtrTraits,
253 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
254 S: SizeTracker,
255{
256 head: *mut P::Target,
277
278 size: S,
281
282 #[pin]
286 _pin: core::marker::PhantomPinned,
287
288 _phantom: core::marker::PhantomData<(P, Tag)>,
289}
290
291impl<P, Tag, S> DoublyLinkedList<P, Tag, S>
292where
293 P: PtrTraits,
294 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
295 S: SizeTracker,
296{
297 pub fn new() -> impl PinInit<Self, core::convert::Infallible> {
299 pin_init!(&this in Self {
300 head: make_sentinel(this.as_ptr()),
301 size: S::INIT,
302 _pin: core::marker::PhantomPinned,
303 _phantom: core::marker::PhantomData,
304 })
305 }
306
307 fn get_sentinel(&self) -> *mut P::Target {
308 make_sentinel(self as *const Self as *mut Self)
309 }
310
311 fn get_tail(&self) -> *mut P::Target {
312 if self.is_empty() {
313 self.get_sentinel()
314 } else {
315 unsafe { *(*self.head).get_node().prev.get() }
319 }
320 }
321
322 unsafe fn set_tail(&self, tail: *mut P::Target) {
326 debug_assert!(!self.is_empty());
327 unsafe {
331 *(*self.head).get_node().prev.get() = tail;
332 }
333 }
334
335 unsafe fn get_node_ref<'a>(&self, ptr: *mut P::Target) -> &'a DoublyLinkedListNode<P::Target> {
340 let _ = self;
341 unsafe { &(*ptr) }.get_node()
343 }
344
345 pub fn is_empty(&self) -> bool {
347 is_sentinel_ptr(self.head)
348 }
349
350 pub fn front(&self) -> Option<&P::Target> {
352 if self.is_empty() { None } else { unsafe { Some(&*self.head) } }
353 }
354
355 pub fn back(&self) -> Option<&P::Target> {
357 let tail = self.get_tail();
358 if is_sentinel_ptr(tail) { None } else { unsafe { Some(&*tail) } }
359 }
360
361 pub fn push_front(&mut self, ptr: P)
367 where
368 P: ManagedPtr,
369 {
370 unsafe { self.push_front_raw(ptr) }
373 }
374
375 pub unsafe fn push_front_raw(&mut self, ptr: P) {
386 let head = self.head;
387 let mut cursor = CursorMut { list: self, current: head };
388 unsafe {
390 cursor.insert_before_raw(ptr);
391 }
392 }
393
394 pub fn push_back(&mut self, ptr: P)
400 where
401 P: ManagedPtr,
402 {
403 unsafe { self.push_back_raw(ptr) }
406 }
407
408 pub unsafe fn push_back_raw(&mut self, ptr: P) {
419 let sentinel = self.get_sentinel();
420 let mut cursor = CursorMut { list: self, current: sentinel };
421 unsafe {
423 cursor.insert_before_raw(ptr);
424 }
425 }
426
427 pub fn pop_front(&mut self) -> Option<P> {
429 if self.is_empty() {
430 return None;
431 }
432 let head = self.head;
433 let mut cursor = CursorMut { list: self, current: head };
434 cursor.erase()
435 }
436
437 pub fn pop_back(&mut self) -> Option<P> {
439 if self.is_empty() {
440 return None;
441 }
442 let tail = self.get_tail();
443 let mut cursor = CursorMut { list: self, current: tail };
444 cursor.erase()
445 }
446
447 pub fn clear(&mut self) {
449 while let Some(_) = self.pop_front() {}
450 }
451
452 pub unsafe fn erase(&mut self, obj: &P::Target) -> Option<P> {
459 let ptr = obj as *const P::Target as *mut P::Target;
460 let node = obj.get_node();
461
462 if !node.in_container() {
463 return None;
464 }
465
466 let mut cursor = self.cursor_mut();
467 cursor.current = ptr;
468 cursor.erase()
469 }
470
471 pub unsafe fn replace_raw(&mut self, obj: &P::Target, replacement: P) -> Option<P> {
478 let ptr = obj as *const P::Target as *mut P::Target;
479 let node = obj.get_node();
480
481 if !node.in_container() {
482 return None;
483 }
484
485 let mut cursor = self.cursor_mut();
486 cursor.current = ptr;
487 unsafe { cursor.replace_raw(replacement) }
489 }
490
491 pub fn erase_if<F>(&mut self, mut f: F) -> Option<P>
494 where
495 F: FnMut(&P::Target) -> bool,
496 {
497 let mut cursor = self.cursor_mut();
498 while let Some(item) = cursor.get() {
499 if f(item) {
500 return cursor.erase();
501 } else {
502 cursor.move_next();
503 }
504 }
505 None
506 }
507
508 pub fn find_if<F>(&self, mut f: F) -> Option<&P::Target>
510 where
511 F: FnMut(&P::Target) -> bool,
512 {
513 self.iter().find(|&x| f(x))
514 }
515
516 pub fn cursor_mut(&mut self) -> CursorMut<'_, P, Tag, S> {
518 let head = self.head;
519 CursorMut { list: self, current: head }
520 }
521
522 pub unsafe fn cursor_at(&mut self, obj: &P::Target) -> CursorMut<'_, P, Tag, S> {
530 assert!(obj.get_node().in_container(), "Object must be in a container");
531 CursorMut { list: self, current: obj as *const P::Target as *mut P::Target }
532 }
533
534 pub fn iter(&self) -> Iterator<'_, P, Tag> {
535 Iterator::new(self)
536 }
537
538 pub fn forward_iter(&self) -> ForwardIterator<'_, P, Tag> {
540 ForwardIterator::new(self.head)
541 }
542
543 pub fn reverse_iter(&self) -> ReverseIterator<'_, P, Tag> {
545 ReverseIterator::new(self.get_tail())
546 }
547}
548
549impl<P, Tag> DoublyLinkedList<P, Tag, TrackingSize>
550where
551 P: PtrTraits,
552 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
553{
554 pub fn len(&self) -> usize {
556 self.size.get()
557 }
558}
559
560#[pinned_drop]
561impl<P, Tag, S> PinnedDrop for DoublyLinkedList<P, Tag, S>
562where
563 P: PtrTraits,
564 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
565 S: SizeTracker,
566{
567 fn drop(self: Pin<&mut Self>) {
568 if P::IS_MANAGED {
569 let me = unsafe { self.get_unchecked_mut() };
571 me.clear();
572 } else {
573 debug_assert!(self.is_empty(), "List must be empty on destruction");
574 if S::IS_TRACKING {
575 debug_assert_eq!(self.size.get(), 0, "Size must be zero on destruction");
576 }
577 }
578 }
579}
580
581pub struct CursorMut<'a, P, Tag = DefaultObjectTag, S = NonTrackingSize>
583where
584 P: PtrTraits,
585 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
586 S: SizeTracker,
587{
588 list: &'a mut DoublyLinkedList<P, Tag, S>,
589 current: *mut P::Target,
590}
591
592impl<'a, P, Tag, S> CursorMut<'a, P, Tag, S>
593where
594 P: PtrTraits,
595 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
596 S: SizeTracker,
597{
598 pub fn get(&self) -> Option<&P::Target> {
599 if is_sentinel_ptr(self.current) { None } else { unsafe { Some(&*self.current) } }
600 }
601
602 pub fn get_mut(&mut self) -> Option<&mut P::Target> {
603 if is_sentinel_ptr(self.current) { None } else { unsafe { Some(&mut *self.current) } }
604 }
605
606 pub fn move_next(&mut self) {
607 if !is_sentinel_ptr(self.current) {
608 let node = unsafe { self.list.get_node_ref(self.current) };
610 self.current = node.get_next();
611 }
612 }
613
614 pub fn move_prev(&mut self) {
615 if !is_sentinel_ptr(self.current) {
616 let node = unsafe { self.list.get_node_ref(self.current) };
618 let prev = node.get_prev();
619 if self.current == self.list.head {
620 self.current = self.list.get_sentinel(); } else {
622 self.current = prev;
623 }
624 } else {
625 self.current = self.list.get_tail();
627 }
628 }
629
630 pub fn insert_after(&mut self, ptr: P)
637 where
638 P: ManagedPtr,
639 {
640 unsafe { self.insert_after_raw(ptr) }
644 }
645
646 pub unsafe fn insert_after_raw(&mut self, ptr: P) {
657 assert!(!is_sentinel_ptr(self.current), "Cannot insert after end sentinel");
658 let raw = P::into_raw(ptr);
659 let node = unsafe { self.list.get_node_ref(raw) };
661 assert!(!node.in_container());
662
663 let current_node = unsafe { self.list.get_node_ref(self.current) };
665 let next = current_node.get_next();
666
667 let current_save = self.current;
668 self.current = next;
669 unsafe {
672 self.insert_chain_before(raw, raw, 1);
673 }
674 self.current = current_save;
675 }
676
677 pub fn replace(&mut self, replacement: P) -> Option<P>
684 where
685 P: ManagedPtr,
686 {
687 unsafe { self.replace_raw(replacement) }
690 }
691
692 pub unsafe fn replace_raw(&mut self, replacement: P) -> Option<P> {
704 if is_sentinel_ptr(self.current) {
705 return None;
706 }
707 unsafe {
710 self.insert_before_raw(replacement);
711 }
712 self.erase()
713 }
714
715 pub fn insert_before(&mut self, ptr: P)
721 where
722 P: ManagedPtr,
723 {
724 unsafe { self.insert_before_raw(ptr) }
727 }
728
729 pub unsafe fn insert_before_raw(&mut self, ptr: P) {
740 let raw = P::into_raw(ptr);
741 let node = unsafe { self.list.get_node_ref(raw) };
743 assert!(!node.in_container());
744
745 unsafe {
747 self.insert_chain_before(raw, raw, 1);
748 }
749 }
750
751 unsafe fn insert_chain_before(
762 &mut self,
763 chain_head: *mut P::Target,
764 chain_tail: *mut P::Target,
765 count: usize,
766 ) {
767 let chain_tail_node = unsafe { self.list.get_node_ref(chain_tail) };
769 chain_tail_node.set_next(self.current);
770
771 if self.list.is_empty() {
772 let chain_head_node = unsafe { self.list.get_node_ref(chain_head) };
774 chain_head_node.set_prev(chain_tail);
775 self.list.head = chain_head;
776 } else {
777 let prev = if self.current == self.list.head || is_sentinel_ptr(self.current) {
778 self.list.get_tail()
779 } else {
780 let current_node = unsafe { self.list.get_node_ref(self.current) };
782 current_node.get_prev()
783 };
784
785 let chain_head_node = unsafe { self.list.get_node_ref(chain_head) };
787 chain_head_node.set_prev(prev);
788
789 if self.current != self.list.head {
791 let prev_node = unsafe { self.list.get_node_ref(prev) };
793 prev_node.set_next(chain_head);
794 }
795
796 if !is_sentinel_ptr(self.current) {
798 let current_node = unsafe { self.list.get_node_ref(self.current) };
800 current_node.set_prev(chain_tail);
801 }
802
803 if self.current == self.list.head {
805 self.list.head = chain_head;
806 }
807
808 if is_sentinel_ptr(self.current) {
810 unsafe {
812 self.list.set_tail(chain_tail);
813 }
814 }
815 }
816
817 if S::IS_TRACKING {
818 self.list.size.set(self.list.size.get() + count);
819 }
820 }
821
822 pub fn splice(&mut self, other: &mut DoublyLinkedList<P, Tag, S>) {
836 if other.is_empty() {
837 return;
838 }
839
840 let other_head = other.head;
841 let other_tail = other.get_tail();
842 let count = if S::IS_TRACKING { other.size.get() } else { 0 };
843
844 unsafe {
847 self.insert_chain_before(other_head, other_tail, count);
848 }
849
850 other.head = other.get_sentinel();
851 if S::IS_TRACKING {
852 other.size.set(0);
853 }
854 }
855
856 pub fn erase(&mut self) -> Option<P> {
857 if is_sentinel_ptr(self.current) {
858 return None;
859 }
860 let ptr = self.current;
861 let node = unsafe { self.list.get_node_ref(ptr) };
863 let next = node.get_next();
864 let prev = node.get_prev();
865
866 self.list.size.decrement();
867
868 if self.list.head == ptr && is_sentinel_ptr(next) {
869 self.list.head = self.list.get_sentinel();
870 } else {
871 if self.current != self.list.head {
873 let prev_node = unsafe { self.list.get_node_ref(prev) };
875 prev_node.set_next(next);
876 }
877
878 if !is_sentinel_ptr(next) {
880 let next_node = unsafe { self.list.get_node_ref(next) };
882 next_node.set_prev(prev);
883 }
884
885 if self.current == self.list.head {
887 self.list.head = next;
888 }
889
890 if is_sentinel_ptr(next) {
892 unsafe {
894 self.list.set_tail(prev);
895 }
896 }
897 }
898
899 node.set_next(core::ptr::null_mut());
900 node.set_prev(core::ptr::null_mut());
901
902 self.current = next;
903 Some(unsafe { P::from_raw(ptr) })
905 }
906}
907
908pub struct Iterator<'a, P, Tag = DefaultObjectTag>
910where
911 P: PtrTraits,
912 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
913{
914 front: ForwardIterator<'a, P, Tag>,
915 back: ReverseIterator<'a, P, Tag>,
916}
917
918impl<'a, P, Tag> Iterator<'a, P, Tag>
919where
920 P: PtrTraits,
921 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
922{
923 fn new<S: SizeTracker>(list: &'a DoublyLinkedList<P, Tag, S>) -> Self {
924 if list.is_empty() {
925 Self {
926 front: ForwardIterator::new(crate::make_sentinel_null()),
927 back: ReverseIterator::new(crate::make_sentinel_null()),
928 }
929 } else {
930 Self {
931 front: ForwardIterator::new(list.head),
932 back: ReverseIterator::new(list.get_tail()),
933 }
934 }
935 }
936}
937
938impl<'a, P, Tag> core::iter::Iterator for Iterator<'a, P, Tag>
939where
940 P: PtrTraits,
941 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
942{
943 type Item = &'a P::Target;
944
945 fn next(&mut self) -> Option<Self::Item> {
946 let met = self.front.current == self.back.current;
947 let item = self.front.next();
948 if item.is_some() {
949 if met {
950 self.front.current = crate::make_sentinel_null();
951 self.back.current = crate::make_sentinel_null();
952 }
953 }
954 item
955 }
956}
957
958impl<'a, P, Tag> core::iter::DoubleEndedIterator for Iterator<'a, P, Tag>
959where
960 P: PtrTraits,
961 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
962{
963 fn next_back(&mut self) -> Option<Self::Item> {
964 let met = self.front.current == self.back.current;
965 let item = self.back.next();
966 if item.is_some() {
967 if met {
968 self.front.current = crate::make_sentinel_null();
969 self.back.current = crate::make_sentinel_null();
970 }
971 }
972 item
973 }
974}
975
976pub struct ForwardIterator<'a, P, Tag = DefaultObjectTag>
978where
979 P: PtrTraits,
980 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
981{
982 current: *mut P::Target,
983 _phantom: core::marker::PhantomData<&'a (P, Tag)>,
984}
985
986impl<'a, P, Tag> ForwardIterator<'a, P, Tag>
987where
988 P: PtrTraits,
989 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
990{
991 fn new(current: *mut P::Target) -> Self {
992 Self { current, _phantom: core::marker::PhantomData }
993 }
994
995 pub fn from_element(obj: &'a P::Target) -> Self {
1001 assert!(obj.get_node().in_container(), "Object must be in a container");
1002 Self { current: obj as *const _ as *mut _, _phantom: core::marker::PhantomData }
1003 }
1004}
1005
1006impl<'a, P, Tag> core::iter::Iterator for ForwardIterator<'a, P, Tag>
1007where
1008 P: PtrTraits,
1009 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1010{
1011 type Item = &'a P::Target;
1012
1013 fn next(&mut self) -> Option<Self::Item> {
1014 if is_sentinel_ptr(self.current) {
1015 None
1016 } else {
1017 let current = unsafe { &*self.current };
1021 self.current = current.get_node().get_next();
1022 Some(current)
1023 }
1024 }
1025}
1026
1027pub struct ReverseIterator<'a, P, Tag = DefaultObjectTag>
1029where
1030 P: PtrTraits,
1031 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1032{
1033 current: *mut P::Target,
1034 _phantom: core::marker::PhantomData<&'a (P, Tag)>,
1035}
1036
1037impl<'a, P, Tag> ReverseIterator<'a, P, Tag>
1038where
1039 P: PtrTraits,
1040 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1041{
1042 fn new(current: *mut P::Target) -> Self {
1043 Self { current, _phantom: core::marker::PhantomData }
1044 }
1045
1046 pub fn from_element(obj: &'a P::Target) -> Self {
1052 assert!(obj.get_node().in_container(), "Object must be in a container");
1053 Self { current: obj as *const _ as *mut _, _phantom: core::marker::PhantomData }
1054 }
1055}
1056
1057impl<'a, P, Tag> core::iter::Iterator for ReverseIterator<'a, P, Tag>
1058where
1059 P: PtrTraits,
1060 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1061{
1062 type Item = &'a P::Target;
1063
1064 fn next(&mut self) -> Option<Self::Item> {
1065 if is_sentinel_ptr(self.current) {
1066 None
1067 } else {
1068 let current = unsafe { &*self.current };
1072 let prev = current.get_node().get_prev();
1073
1074 let prev_node = unsafe { &*prev }.get_node();
1077 if is_sentinel_ptr(prev_node.get_next()) {
1078 self.current = prev_node.get_next();
1081 } else {
1082 self.current = prev;
1083 }
1084 Some(current)
1085 }
1086 }
1087}
1088
1089pub unsafe fn remove_from_container<T, Tag, P>(obj: &T) -> Option<P>
1097where
1098 P: PtrTraits<Target = T>,
1099 T: DoublyLinkedListContainable<T, Tag>,
1100{
1101 let node = obj.get_node();
1102 if !node.in_container() {
1103 return None;
1104 }
1105
1106 let mut current = obj as *const T as *mut T;
1107 unsafe {
1108 while !is_sentinel_ptr(current) {
1109 current = (*current).get_node().get_next();
1110 }
1111
1112 let list_ptr = crate::sentinel::unmake_sentinel::<
1113 DoublyLinkedList<P, Tag, NonTrackingSize>,
1114 T,
1115 >(current);
1116 let list_ref = &mut *list_ptr;
1117
1118 list_ref.erase(obj)
1119 }
1120}
1121
1122impl<P, Tag, S> core::fmt::Debug for DoublyLinkedList<P, Tag, S>
1123where
1124 P: PtrTraits,
1125 P::Target: DoublyLinkedListContainable<P::Target, Tag> + core::fmt::Debug,
1126 S: SizeTracker,
1127{
1128 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1129 f.debug_list().entries(self.iter()).finish()
1130 }
1131}
1132
1133#[cfg(test)]
1134mod tests {
1135 extern crate alloc;
1136 use super::*;
1137 use crate::intrusive_container_test_support::*;
1138 use crate::ref_ptr::RefPtr;
1139 use crate::unique_ptr::UniquePtr;
1140 use core::ffi::c_void;
1141 use pin_init::stack_pin_init;
1142
1143 #[derive(crate::DoublyLinkedListContainable, crate::Recyclable)]
1144 struct TestObject {
1145 value: i32,
1146 #[dll_node]
1147 node: DoublyLinkedListNode<TestObject>,
1148 }
1149
1150 impl TestObject {
1151 fn new(value: i32) -> Self {
1152 Self { value, node: DoublyLinkedListNode::new() }
1153 }
1154 }
1155
1156 impl TestValue for TestObject {
1157 fn new(value: i32) -> Self {
1158 Self::new(value)
1159 }
1160 }
1161
1162 ::zr::static_assert!(
1163 core::mem::size_of::<DoublyLinkedList<*mut TestObject>>()
1164 == core::mem::size_of::<*mut TestObject>()
1165 );
1166 ::zr::static_assert!(
1167 core::mem::align_of::<DoublyLinkedList<*mut TestObject>>()
1168 == core::mem::align_of::<*mut TestObject>()
1169 );
1170
1171 ::zr::static_assert!(
1172 core::mem::size_of::<DoublyLinkedList<*mut TestObject, DefaultObjectTag, TrackingSize>>()
1173 == 2 * core::mem::size_of::<*mut TestObject>()
1174 );
1175 ::zr::static_assert!(
1176 core::mem::align_of::<DoublyLinkedList<*mut TestObject, DefaultObjectTag, TrackingSize>>()
1177 == core::mem::align_of::<*mut TestObject>()
1178 );
1179
1180 ::zr::static_assert!(
1181 core::mem::size_of::<ForwardIterator<'_, *mut TestObject>>()
1182 == core::mem::size_of::<*mut TestObject>()
1183 );
1184 ::zr::static_assert!(
1185 core::mem::align_of::<ForwardIterator<'_, *mut TestObject>>()
1186 == core::mem::align_of::<*mut TestObject>()
1187 );
1188
1189 ::zr::static_assert!(
1190 core::mem::size_of::<ReverseIterator<'_, *mut TestObject>>()
1191 == core::mem::size_of::<*mut TestObject>()
1192 );
1193 ::zr::static_assert!(
1194 core::mem::align_of::<ReverseIterator<'_, *mut TestObject>>()
1195 == core::mem::align_of::<*mut TestObject>()
1196 );
1197
1198 #[derive(crate::DoublyLinkedListContainable, crate::Recyclable)]
1199 struct UniqueTestObject {
1200 value: i32,
1201 #[dll_node]
1202 node: DoublyLinkedListNode<UniqueTestObject>,
1203 }
1204
1205 impl UniqueTestObject {
1206 fn new(value: i32) -> Self {
1207 Self { value, node: DoublyLinkedListNode::new() }
1208 }
1209 }
1210
1211 impl TestValue for UniqueTestObject {
1212 fn new(value: i32) -> Self {
1213 Self::new(value)
1214 }
1215 }
1216
1217 #[fbl::ref_counted]
1218 #[derive(crate::DoublyLinkedListContainable, crate::Recyclable)]
1219 #[repr(C)]
1220 pub struct RefTestObject {
1221 value: i32,
1222 #[dll_node]
1223 node: DoublyLinkedListNode<RefTestObject>,
1224 }
1225
1226 impl TestValue for RefTestObject {
1227 fn new_ref_counted(value: i32) -> RefPtr<Self> {
1228 crate::make_ref_counted!(RefTestObject {
1229 value: value,
1230 node: DoublyLinkedListNode::new()
1231 })
1232 .unwrap()
1233 }
1234 }
1235
1236 macro_rules! generate_list_tests {
1237 ($mod_name:ident, $ptr_type:ty, $factory_type:ty, $get_val:expr, $push:expr) => {
1238 mod $mod_name {
1239 use super::*;
1240
1241 #[test]
1242 fn test_basic() {
1243 let mut factory = <$factory_type>::new();
1244 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1245 let list = unsafe { list.get_unchecked_mut() };
1246 assert!(list.is_empty());
1247
1248 let obj1 = factory.create(1);
1249 let obj2 = factory.create(2);
1250
1251 $push(list, obj1);
1252 $push(list, obj2);
1253
1254 assert!(!list.is_empty());
1255
1256 let mut iter = list.iter();
1257 assert_eq!(iter.next().unwrap().value, 2);
1258 assert_eq!(iter.next().unwrap().value, 1);
1259 assert!(iter.next().is_none());
1260
1261 list.clear();
1262 assert!(list.is_empty());
1263 }
1264
1265 #[test]
1266 fn test_double_ended_iterator() {
1267 let mut factory = <$factory_type>::new();
1268 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1269 let list = unsafe { list.get_unchecked_mut() };
1270 let obj1 = factory.create(1);
1271 let obj2 = factory.create(2);
1272 let obj3 = factory.create(3);
1273
1274 $push(list, obj1);
1275 $push(list, obj2);
1276 $push(list, obj3);
1277
1278 let mut iter = list.iter();
1279 assert_eq!(iter.next().unwrap().value, 3);
1280 assert_eq!(iter.next_back().unwrap().value, 1);
1281 assert_eq!(iter.next().unwrap().value, 2);
1282 assert!(iter.next().is_none());
1283 assert!(iter.next_back().is_none());
1284
1285 list.clear();
1286 }
1287
1288 #[test]
1289 fn test_explicit_pops() {
1290 let mut factory = <$factory_type>::new();
1291 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1292 let list = unsafe { list.get_unchecked_mut() };
1293 let obj1 = factory.create(1);
1294 let obj2 = factory.create(2);
1295
1296 $push(list, obj1);
1297 $push(list, obj2);
1298
1299 let p1 = list.pop_front();
1300 assert!(p1.is_some());
1301 let p2 = list.pop_front();
1302 assert!(p2.is_some());
1303 assert!(list.pop_front().is_none());
1304 }
1305
1306 #[test]
1307 fn test_cursor_move_prev() {
1308 let mut factory = <$factory_type>::new();
1309 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1310 let list = unsafe { list.get_unchecked_mut() };
1311 let obj1 = factory.create(1);
1312 let obj2 = factory.create(2);
1313 let obj3 = factory.create(3);
1314
1315 $push(list, obj1);
1316 $push(list, obj2);
1317 $push(list, obj3);
1318
1319 let (a, b, c) = {
1320 let mut iter = list.iter();
1321 (
1322 $get_val(iter.next().unwrap()),
1323 $get_val(iter.next().unwrap()),
1324 $get_val(iter.next().unwrap()),
1325 )
1326 };
1327
1328 let mut cursor = list.cursor_mut();
1329 assert_eq!($get_val(cursor.get().unwrap()), a);
1330
1331 cursor.move_prev();
1332 assert!(cursor.get().is_none()); cursor.move_prev();
1335 assert_eq!($get_val(cursor.get().unwrap()), c);
1336
1337 cursor.move_prev();
1338 assert_eq!($get_val(cursor.get().unwrap()), b);
1339
1340 cursor.move_prev();
1341 assert_eq!($get_val(cursor.get().unwrap()), a);
1342
1343 list.clear();
1344 }
1345
1346 #[test]
1347 fn test_cursor_insert_after() {
1348 let mut factory = <$factory_type>::new();
1349 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1350 let list = unsafe { list.get_unchecked_mut() };
1351 let obj1 = factory.create(1);
1352 let obj2 = factory.create(2);
1353 let obj3 = factory.create(3);
1354
1355 $push(list, obj1);
1356
1357 let mut cursor = list.cursor_mut();
1358 unsafe {
1359 cursor.insert_after_raw(obj3);
1360 cursor.insert_after_raw(obj2);
1361 }
1362
1363 let mut iter = list.iter();
1364 assert_eq!($get_val(iter.next().unwrap()), 1);
1365 assert_eq!($get_val(iter.next().unwrap()), 2);
1366 assert_eq!($get_val(iter.next().unwrap()), 3);
1367 assert!(iter.next().is_none());
1368
1369 list.clear();
1370 }
1371
1372 #[test]
1373 fn test_pop_back() {
1374 let mut factory = <$factory_type>::new();
1375 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1376 let list = unsafe { list.get_unchecked_mut() };
1377 let obj1 = factory.create(1);
1378 let obj2 = factory.create(2);
1379
1380 $push(list, obj1);
1381 $push(list, obj2);
1382
1383 let p1 = list.pop_back();
1384 assert!(p1.is_some());
1385 let p2 = list.pop_back();
1386 assert!(p2.is_some());
1387 assert!(list.pop_back().is_none());
1388 }
1389
1390 #[test]
1391 fn test_erase() {
1392 let mut factory = <$factory_type>::new();
1393 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1394 let list = unsafe { list.get_unchecked_mut() };
1395 let obj1 = factory.create(1);
1396 let obj2 = factory.create(2);
1397 let obj3 = factory.create(3);
1398
1399 $push(list, obj1);
1400 $push(list, obj2);
1401 $push(list, obj3);
1402
1403 let mut cursor = list.cursor_mut();
1404 cursor.move_next();
1405 let erased = cursor.erase();
1406 assert!(erased.is_some());
1407 factory.cleanup(erased.unwrap());
1408
1409 let mut iter = list.iter();
1410 assert!(iter.next().is_some());
1411 assert!(iter.next().is_some());
1412 assert!(iter.next().is_none());
1413
1414 list.clear();
1415 }
1416
1417 #[test]
1418 fn test_erase_if() {
1419 let mut factory = <$factory_type>::new();
1420 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1421 let list = unsafe { list.get_unchecked_mut() };
1422 let obj1 = factory.create(1);
1423 let obj2 = factory.create(2);
1424 let obj3 = factory.create(3);
1425
1426 $push(list, obj1);
1427 $push(list, obj2);
1428 $push(list, obj3);
1429
1430 let erased = list.erase_if(|o| o.value == 2);
1431 assert!(erased.is_some());
1432 assert_eq!($get_val(erased.unwrap().get_ref()), 2);
1433
1434 let mut iter = list.iter();
1435 assert_eq!($get_val(iter.next().unwrap()), 3);
1436 assert_eq!($get_val(iter.next().unwrap()), 1);
1437 assert!(iter.next().is_none());
1438
1439 list.clear();
1440 }
1441
1442 #[test]
1443 fn test_find_if() {
1444 let mut factory = <$factory_type>::new();
1445 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1446 let list = unsafe { list.get_unchecked_mut() };
1447 let obj1 = factory.create(1);
1448 let obj2 = factory.create(2);
1449
1450 $push(list, obj1);
1451 $push(list, obj2);
1452
1453 let found = list.find_if(|o| o.value == 1);
1454 assert!(found.is_some());
1455 assert_eq!(found.unwrap().value, 1);
1456
1457 let found = list.find_if(|o| o.value == 3);
1458 assert!(found.is_none());
1459
1460 list.clear();
1461 }
1462
1463 #[test]
1464 fn test_complete_reverse_iteration() {
1465 let mut factory = <$factory_type>::new();
1466 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1467 let list = unsafe { list.get_unchecked_mut() };
1468 let obj1 = factory.create(1);
1469 let obj2 = factory.create(2);
1470 let obj3 = factory.create(3);
1471
1472 $push(list, obj1);
1473 $push(list, obj2);
1474 $push(list, obj3);
1475
1476 let (a, b, c) = {
1477 let mut iter = list.iter();
1478 (
1479 $get_val(iter.next().unwrap()),
1480 $get_val(iter.next().unwrap()),
1481 $get_val(iter.next().unwrap()),
1482 )
1483 };
1484
1485 let mut iter = list.iter();
1486 assert_eq!($get_val(iter.next_back().unwrap()), c);
1487 assert_eq!($get_val(iter.next_back().unwrap()), b);
1488 assert_eq!($get_val(iter.next_back().unwrap()), a);
1489 assert!(iter.next_back().is_none());
1490
1491 list.clear();
1492 }
1493 }
1494 };
1495 }
1496
1497 generate_list_tests!(
1498 raw_ptr_tests,
1499 *mut TestObject,
1500 RawFactory<TestObject>,
1501 |p: &TestObject| p.value,
1502 |list: &mut DoublyLinkedList<*mut TestObject>, obj| unsafe {
1503 list.push_front_raw(obj);
1504 }
1505 );
1506
1507 generate_list_tests!(
1508 unique_ptr_tests,
1509 UniquePtr<UniqueTestObject>,
1510 UniqueFactory<UniqueTestObject>,
1511 |p: &UniqueTestObject| p.value,
1512 |list: &mut DoublyLinkedList<UniquePtr<UniqueTestObject>>, obj| list.push_front(obj)
1513 );
1514
1515 generate_list_tests!(
1516 ref_ptr_tests,
1517 RefPtr<RefTestObject>,
1518 RefFactory<RefTestObject>,
1519 |p: &RefTestObject| p.value,
1520 |list: &mut DoublyLinkedList<RefPtr<RefTestObject>>, obj| list.push_front(obj)
1521 );
1522
1523 #[test]
1524 fn test_tracking_size() {
1525 stack_pin_init!(let list =
1526 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1527 let list = unsafe { list.get_unchecked_mut() };
1528
1529 assert_eq!(list.len(), 0);
1530 list.push_front(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1531 assert_eq!(list.len(), 1);
1532 list.push_front(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1533 assert_eq!(list.len(), 2);
1534 list.pop_front();
1535 assert_eq!(list.len(), 1);
1536 list.clear();
1537 assert_eq!(list.len(), 0);
1538 }
1539
1540 #[test]
1541 fn test_insert_before() {
1542 stack_pin_init!(let list =
1543 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1544 let list = unsafe { list.get_unchecked_mut() };
1545
1546 let mut cursor = list.cursor_mut();
1547 cursor.insert_before(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1548 assert_eq!(list.len(), 1);
1549 assert_eq!(list.front().unwrap().value, 1);
1550
1551 let mut cursor = list.cursor_mut();
1552 cursor.insert_before(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1553 assert_eq!(list.len(), 2);
1554 assert_eq!(list.front().unwrap().value, 2);
1555
1556 let mut cursor = list.cursor_mut();
1557 cursor.move_next(); cursor.insert_before(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1559 assert_eq!(list.len(), 3);
1560
1561 let mut cursor = list.cursor_mut();
1562 while cursor.get().unwrap().value != 1 {
1563 cursor.move_next();
1564 }
1565 cursor.move_next(); cursor.insert_before(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
1567 assert_eq!(list.len(), 4);
1568
1569 let mut iter = list.iter();
1570 assert_eq!(iter.next().unwrap().value, 2);
1571 assert_eq!(iter.next().unwrap().value, 3);
1572 assert_eq!(iter.next().unwrap().value, 1);
1573 assert_eq!(iter.next().unwrap().value, 4);
1574 assert!(iter.next().is_none());
1575
1576 list.clear();
1577 }
1578
1579 #[test]
1580 fn test_splice_middle() {
1581 stack_pin_init!(let list1 =
1582 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1583 let list1 = unsafe { list1.get_unchecked_mut() };
1584 stack_pin_init!(let list2 =
1585 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1586 let list2 = unsafe { list2.get_unchecked_mut() };
1587
1588 list1.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1589 list1.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1590 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1591 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
1592
1593 let mut cursor = list1.cursor_mut();
1594 cursor.move_next(); cursor.splice(list2);
1597
1598 assert!(list2.is_empty());
1599 assert_eq!(list1.len(), 4);
1600
1601 let mut iter = list1.iter();
1602 assert_eq!(iter.next().unwrap().value, 1);
1603 assert_eq!(iter.next().unwrap().value, 3);
1604 assert_eq!(iter.next().unwrap().value, 4);
1605 assert_eq!(iter.next().unwrap().value, 2);
1606 assert!(iter.next().is_none());
1607
1608 list1.clear();
1609 }
1610
1611 #[test]
1612 fn test_splice_head() {
1613 stack_pin_init!(let list1 =
1614 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1615 let list1 = unsafe { list1.get_unchecked_mut() };
1616 stack_pin_init!(let list2 =
1617 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1618 let list2 = unsafe { list2.get_unchecked_mut() };
1619
1620 list1.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1621 list1.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1622 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1623 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
1624
1625 let mut cursor = list1.cursor_mut();
1626
1627 cursor.splice(list2);
1628
1629 assert!(list2.is_empty());
1630 assert_eq!(list1.len(), 4);
1631
1632 let mut iter = list1.iter();
1633 assert_eq!(iter.next().unwrap().value, 3);
1634 assert_eq!(iter.next().unwrap().value, 4);
1635 assert_eq!(iter.next().unwrap().value, 1);
1636 assert_eq!(iter.next().unwrap().value, 2);
1637 assert!(iter.next().is_none());
1638
1639 list1.clear();
1640 }
1641
1642 #[test]
1643 fn test_splice_tail() {
1644 stack_pin_init!(let list1 =
1645 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1646 let list1 = unsafe { list1.get_unchecked_mut() };
1647 stack_pin_init!(let list2 =
1648 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1649 let list2 = unsafe { list2.get_unchecked_mut() };
1650
1651 list1.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1652 list1.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1653 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1654 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
1655
1656 let mut cursor = list1.cursor_mut();
1657 cursor.move_next();
1658 cursor.move_next(); cursor.splice(list2);
1661
1662 assert!(list2.is_empty());
1663 assert_eq!(list1.len(), 4);
1664
1665 let mut iter = list1.iter();
1666 assert_eq!(iter.next().unwrap().value, 1);
1667 assert_eq!(iter.next().unwrap().value, 2);
1668 assert_eq!(iter.next().unwrap().value, 3);
1669 assert_eq!(iter.next().unwrap().value, 4);
1670 assert!(iter.next().is_none());
1671
1672 list1.clear();
1673 }
1674
1675 #[test]
1676 fn test_splice_empty() {
1677 stack_pin_init!(let list1 =
1678 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1679 let list1 = unsafe { list1.get_unchecked_mut() };
1680 stack_pin_init!(let list2 =
1681 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1682 let list2 = unsafe { list2.get_unchecked_mut() };
1683
1684 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1685 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1686
1687 let mut cursor = list1.cursor_mut();
1688 cursor.splice(list2);
1689
1690 assert!(list2.is_empty());
1691 assert_eq!(list1.len(), 2);
1692
1693 let mut iter = list1.iter();
1694 assert_eq!(iter.next().unwrap().value, 1);
1695 assert_eq!(iter.next().unwrap().value, 2);
1696 assert!(iter.next().is_none());
1697
1698 list1.clear();
1699 }
1700
1701 #[test]
1702 fn test_splice_non_tracking() {
1703 stack_pin_init!(let list1 =
1704 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, NonTrackingSize>::new());
1705 let list1 = unsafe { list1.get_unchecked_mut() };
1706 stack_pin_init!(let list2 =
1707 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, NonTrackingSize>::new());
1708 let list2 = unsafe { list2.get_unchecked_mut() };
1709
1710 list1.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1711 list1.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1712 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1713 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
1714
1715 let mut cursor = list1.cursor_mut();
1716 cursor.move_next(); cursor.splice(list2);
1719
1720 assert!(list2.is_empty());
1721
1722 let mut iter = list1.iter();
1723 assert_eq!(iter.next().unwrap().value, 1);
1724 assert_eq!(iter.next().unwrap().value, 3);
1725 assert_eq!(iter.next().unwrap().value, 4);
1726 assert_eq!(iter.next().unwrap().value, 2);
1727 assert!(iter.next().is_none());
1728
1729 list1.clear();
1730 }
1731
1732 #[test]
1733 fn test_pop_back() {
1734 stack_pin_init!(let list =
1735 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1736 let list = unsafe { list.get_unchecked_mut() };
1737
1738 list.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1739 list.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1740
1741 assert_eq!(list.len(), 2);
1742 let popped = list.pop_back();
1743 assert!(popped.is_some());
1744 assert_eq!(popped.unwrap().value, 2);
1745 assert_eq!(list.len(), 1);
1746
1747 let popped = list.pop_back();
1748 assert!(popped.is_some());
1749 assert_eq!(popped.unwrap().value, 1);
1750 assert_eq!(list.len(), 0);
1751
1752 assert!(list.pop_back().is_none());
1753 }
1754
1755 #[test]
1756 fn test_erase() {
1757 stack_pin_init!(let list =
1758 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1759 let list = unsafe { list.get_unchecked_mut() };
1760
1761 list.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1762 list.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1763 list.push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1764
1765 assert_eq!(list.len(), 3);
1766
1767 let mut cursor = list.cursor_mut();
1769 cursor.move_next(); let erased = cursor.erase();
1771 assert!(erased.is_some());
1772 assert_eq!(erased.unwrap().value, 2);
1773 assert_eq!(list.len(), 2);
1774
1775 let mut iter = list.iter();
1776 assert_eq!(iter.next().unwrap().value, 1);
1777 assert_eq!(iter.next().unwrap().value, 3);
1778 assert!(iter.next().is_none());
1779
1780 let mut cursor = list.cursor_mut();
1782 let erased = cursor.erase(); assert!(erased.is_some());
1784 assert_eq!(erased.unwrap().value, 1);
1785 assert_eq!(list.len(), 1);
1786 assert_eq!(list.front().unwrap().value, 3); let mut cursor = list.cursor_mut();
1790 let erased = cursor.erase(); assert!(erased.is_some());
1792 assert_eq!(erased.unwrap().value, 3);
1793 assert_eq!(list.len(), 0);
1794 assert!(list.is_empty());
1795
1796 list.clear();
1797 }
1798
1799 #[test]
1800 fn test_erase_if() {
1801 stack_pin_init!(let list =
1802 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1803 let list = unsafe { list.get_unchecked_mut() };
1804
1805 list.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1806 list.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1807 list.push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1808
1809 let erased = list.erase_if(|obj| obj.value % 2 == 0);
1810 assert!(erased.is_some());
1811 assert_eq!(erased.unwrap().value, 2);
1812
1813 assert_eq!(list.len(), 2);
1814 let mut iter = list.iter();
1815 assert_eq!(iter.next().unwrap().value, 1);
1816 assert_eq!(iter.next().unwrap().value, 3);
1817 assert!(iter.next().is_none());
1818
1819 list.clear();
1820 }
1821
1822 #[test]
1823 fn test_erase_by_reference() {
1824 stack_pin_init!(let list =
1825 DoublyLinkedList::<*mut TestObject, DefaultObjectTag, TrackingSize>::new());
1826 let list = unsafe { list.get_unchecked_mut() };
1827 let mut obj1 = TestObject::new(1);
1828 let mut obj2 = TestObject::new(2);
1829 let mut obj3 = TestObject::new(3);
1830
1831 unsafe {
1832 list.push_back_raw(&mut obj1);
1833 list.push_back_raw(&mut obj2);
1834 list.push_back_raw(&mut obj3);
1835 }
1836
1837 assert_eq!(list.len(), 3);
1838
1839 let erased = unsafe { list.erase(&obj2) };
1841 assert!(erased.is_some());
1842 assert_eq!(unsafe { &*erased.unwrap() }.value, 2);
1843 assert_eq!(list.len(), 2);
1844
1845 let mut iter = list.iter();
1846 assert_eq!(iter.next().unwrap().value, 1);
1847 assert_eq!(iter.next().unwrap().value, 3);
1848 assert!(iter.next().is_none());
1849
1850 list.clear();
1851 }
1852
1853 #[test]
1854 fn test_remove_from_container() {
1855 stack_pin_init!(let list = DoublyLinkedList::<*mut TestObject>::new());
1856 let list = unsafe { list.get_unchecked_mut() };
1857 let mut obj1 = TestObject::new(1);
1858 let mut obj2 = TestObject::new(2);
1859 let mut obj3 = TestObject::new(3);
1860
1861 let removed = unsafe {
1863 remove_from_container::<TestObject, DefaultObjectTag, *mut TestObject>(&obj1)
1864 };
1865 assert!(removed.is_none());
1866
1867 unsafe {
1868 list.push_back_raw(&mut obj1);
1869 list.push_back_raw(&mut obj2);
1870 list.push_back_raw(&mut obj3);
1871 }
1872
1873 let removed = unsafe {
1875 remove_from_container::<TestObject, DefaultObjectTag, *mut TestObject>(&obj2)
1876 };
1877 assert!(removed.is_some());
1878 assert_eq!(unsafe { &*removed.unwrap() }.value, 2);
1879
1880 let mut iter = list.iter();
1881 assert_eq!(iter.next().unwrap().value, 1);
1882 assert_eq!(iter.next().unwrap().value, 3);
1883 assert!(iter.next().is_none());
1884
1885 let removed = unsafe {
1887 remove_from_container::<TestObject, DefaultObjectTag, *mut TestObject>(&obj1)
1888 };
1889 assert!(removed.is_some());
1890 assert_eq!(unsafe { &*removed.unwrap() }.value, 1);
1891
1892 let mut iter = list.iter();
1893 assert_eq!(iter.next().unwrap().value, 3);
1894 assert!(iter.next().is_none());
1895
1896 let removed = unsafe {
1898 remove_from_container::<TestObject, DefaultObjectTag, *mut TestObject>(&obj3)
1899 };
1900 assert!(removed.is_some());
1901 assert_eq!(unsafe { &*removed.unwrap() }.value, 3);
1902 assert!(list.is_empty());
1903
1904 list.clear();
1905 }
1906
1907 #[test]
1908 fn test_replace() {
1909 stack_pin_init!(let list =
1910 DoublyLinkedList::<*mut TestObject, DefaultObjectTag, TrackingSize>::new());
1911 let list = unsafe { list.get_unchecked_mut() };
1912 let mut obj1 = TestObject::new(1);
1913 let mut obj2 = TestObject::new(2);
1914 let mut obj3 = TestObject::new(3);
1915
1916 unsafe {
1917 list.push_back_raw(&mut obj1);
1918 list.push_back_raw(&mut obj2);
1919 }
1920
1921 assert_eq!(list.len(), 2);
1922
1923 let old = unsafe { list.replace_raw(&obj2, &mut obj3) };
1924 assert!(old.is_some());
1925 assert_eq!(unsafe { &*old.unwrap() }.value, 2);
1926 assert_eq!(list.len(), 2);
1927
1928 let mut iter = list.iter();
1929 assert_eq!(iter.next().unwrap().value, 1);
1930 assert_eq!(iter.next().unwrap().value, 3);
1931 assert!(iter.next().is_none());
1932
1933 list.clear();
1934 }
1935
1936 #[test]
1937 fn test_cursor_replace() {
1938 stack_pin_init!(let list = DoublyLinkedList::<UniquePtr<UniqueTestObject>>::new());
1939 let list = unsafe { list.get_unchecked_mut() };
1940
1941 let obj1 = UniquePtr::try_new(UniqueTestObject::new(1)).unwrap();
1942 let obj2 = UniquePtr::try_new(UniqueTestObject::new(2)).unwrap();
1943 let obj3 = UniquePtr::try_new(UniqueTestObject::new(3)).unwrap();
1944
1945 list.push_back(obj1);
1946 list.push_back(obj2);
1947
1948 let mut cursor = list.cursor_mut();
1949 cursor.move_next(); let old = cursor.replace(obj3);
1952 assert!(old.is_some());
1953 assert_eq!(old.unwrap().value, 2);
1954
1955 let mut iter = list.iter();
1956 assert_eq!(iter.next().unwrap().value, 1);
1957 assert_eq!(iter.next().unwrap().value, 3);
1958 assert!(iter.next().is_none());
1959
1960 list.clear();
1961 }
1962
1963 struct Tag2;
1964
1965 #[fbl::ref_counted]
1966 #[derive(crate::DoublyLinkedListContainable, crate::Recyclable)]
1967 #[repr(C)]
1968 struct MultiListObject {
1969 value: i32,
1970 #[dll_node]
1971 node1: DoublyLinkedListNode<MultiListObject>,
1972 #[dll_node(tag = Tag2)]
1973 node2: DoublyLinkedListNode<MultiListObject>,
1974 }
1975
1976 #[test]
1977 fn test_multiple_containers() {
1978 stack_pin_init!(let list1 =
1979 DoublyLinkedList::<RefPtr<MultiListObject>, DefaultObjectTag>::new());
1980 let list1 = unsafe { list1.get_unchecked_mut() };
1981 stack_pin_init!(let list2 = DoublyLinkedList::<RefPtr<MultiListObject>, Tag2>::new());
1982 let list2 = unsafe { list2.get_unchecked_mut() };
1983
1984 let obj1 = fbl::make_ref_counted!(MultiListObject {
1985 value: 1,
1986 node1: DoublyLinkedListNode::new(),
1987 node2: DoublyLinkedListNode::new(),
1988 })
1989 .unwrap();
1990
1991 let obj2 = fbl::make_ref_counted!(MultiListObject {
1992 value: 2,
1993 node1: DoublyLinkedListNode::new(),
1994 node2: DoublyLinkedListNode::new(),
1995 })
1996 .unwrap();
1997
1998 list1.push_back(obj1.clone());
1999 list1.push_back(obj2.clone());
2000
2001 list2.push_back(obj2); let mut iter1 = list1.iter();
2004 assert_eq!(iter1.next().unwrap().value, 1);
2005 assert_eq!(iter1.next().unwrap().value, 2);
2006 assert!(iter1.next().is_none());
2007
2008 let mut iter2 = list2.iter();
2009 assert_eq!(iter2.next().unwrap().value, 2);
2010 assert!(iter2.next().is_none());
2011
2012 list1.clear();
2013 list2.clear();
2014 }
2015
2016 use alloc::sync::Arc;
2017 use core::sync::atomic::{AtomicBool, Ordering};
2018
2019 #[derive(crate::DoublyLinkedListContainable, crate::Recyclable)]
2020 struct LifecycleObject {
2021 destroyed: Arc<AtomicBool>,
2022 #[dll_node]
2023 node: DoublyLinkedListNode<LifecycleObject>,
2024 }
2025
2026 impl LifecycleObject {
2027 fn new(destroyed: Arc<AtomicBool>) -> Self {
2028 Self { destroyed, node: DoublyLinkedListNode::new() }
2029 }
2030 }
2031
2032 impl Drop for LifecycleObject {
2033 fn drop(&mut self) {
2034 self.destroyed.store(true, Ordering::Relaxed);
2035 }
2036 }
2037
2038 #[test]
2039 fn test_lifecycle_on_drop() {
2040 let destroyed1 = Arc::new(AtomicBool::new(false));
2041 let destroyed2 = Arc::new(AtomicBool::new(false));
2042
2043 {
2044 stack_pin_init!(let list = DoublyLinkedList::<UniquePtr<LifecycleObject>>::new());
2045 let list = unsafe { list.get_unchecked_mut() };
2046
2047 let obj1 = UniquePtr::try_new(LifecycleObject::new(destroyed1.clone())).unwrap();
2048 let obj2 = UniquePtr::try_new(LifecycleObject::new(destroyed2.clone())).unwrap();
2049
2050 list.push_back(obj1);
2051 list.push_back(obj2);
2052
2053 assert!(!destroyed1.load(Ordering::Relaxed));
2054 assert!(!destroyed2.load(Ordering::Relaxed));
2055 } assert!(destroyed1.load(Ordering::Relaxed));
2058 assert!(destroyed2.load(Ordering::Relaxed));
2059 }
2060
2061 #[test]
2062 fn test_sized_managed_list() {
2063 stack_pin_init!(let list =
2064 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2065 let list = unsafe { list.get_unchecked_mut() };
2066
2067 assert_eq!(list.len(), 0);
2068
2069 let obj1 = UniquePtr::try_new(UniqueTestObject::new(1)).unwrap();
2070 let obj2 = UniquePtr::try_new(UniqueTestObject::new(2)).unwrap();
2071
2072 list.push_back(obj1);
2073 assert_eq!(list.len(), 1);
2074
2075 list.push_back(obj2);
2076 assert_eq!(list.len(), 2);
2077
2078 let popped = list.pop_front();
2079 assert!(popped.is_some());
2080 assert_eq!(list.len(), 1);
2081
2082 list.clear();
2083 assert_eq!(list.len(), 0);
2084 }
2085
2086 #[test]
2087 fn test_unidirectional_iterators() {
2088 stack_pin_init!(let list = DoublyLinkedList::<UniquePtr<UniqueTestObject>>::new());
2089 let list = unsafe { list.get_unchecked_mut() };
2090
2091 list.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2092 list.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2093 list.push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
2094
2095 let mut f_iter = list.forward_iter();
2097 assert_eq!(f_iter.next().unwrap().value, 1);
2098 let obj2_ref = f_iter.next().unwrap();
2099 assert_eq!(obj2_ref.value, 2);
2100 assert_eq!(f_iter.next().unwrap().value, 3);
2101 assert!(f_iter.next().is_none());
2102
2103 let mut f_element_iter =
2105 ForwardIterator::<UniquePtr<UniqueTestObject>>::from_element(obj2_ref);
2106 assert_eq!(f_element_iter.next().unwrap().value, 2);
2107 assert_eq!(f_element_iter.next().unwrap().value, 3);
2108 assert!(f_element_iter.next().is_none());
2109
2110 let mut r_iter = list.reverse_iter();
2112 assert_eq!(r_iter.next().unwrap().value, 3);
2113 let obj2_ref_r = r_iter.next().unwrap();
2114 assert_eq!(obj2_ref_r.value, 2);
2115 assert_eq!(r_iter.next().unwrap().value, 1);
2116 assert!(r_iter.next().is_none());
2117
2118 let mut r_element_iter =
2120 ReverseIterator::<UniquePtr<UniqueTestObject>>::from_element(obj2_ref_r);
2121 assert_eq!(r_element_iter.next().unwrap().value, 2);
2122 assert_eq!(r_element_iter.next().unwrap().value, 1);
2123 assert!(r_element_iter.next().is_none());
2124
2125 list.clear();
2126 }
2127
2128 #[test]
2129 fn test_cursor_at() {
2130 stack_pin_init!(let list =
2131 DoublyLinkedList::<*mut TestObject, DefaultObjectTag, TrackingSize>::new());
2132 let list = unsafe { list.get_unchecked_mut() };
2133 let mut obj1 = TestObject::new(1);
2134 let mut obj2 = TestObject::new(2);
2135 let mut obj3 = TestObject::new(3);
2136
2137 unsafe {
2138 list.push_back_raw(&mut obj1);
2139 list.push_back_raw(&mut obj2);
2140 list.push_back_raw(&mut obj3);
2141 }
2142
2143 let mut cursor = unsafe { list.cursor_at(&obj2) };
2146 assert_eq!(cursor.get().unwrap().value, 2);
2147
2148 cursor.move_next();
2150 assert_eq!(cursor.get().unwrap().value, 3);
2151
2152 let mut cursor = unsafe { list.cursor_at(&obj2) };
2155 cursor.move_prev();
2156 assert_eq!(cursor.get().unwrap().value, 1);
2157
2158 let mut cursor = unsafe { list.cursor_at(&obj2) };
2161 let erased = cursor.erase().unwrap();
2162 assert_eq!(unsafe { &*erased }.value, 2);
2163
2164 let mut iter = list.iter();
2166 assert_eq!(iter.next().unwrap().value, 1);
2167 assert_eq!(iter.next().unwrap().value, 3);
2168 assert!(iter.next().is_none());
2169
2170 list.clear();
2171 }
2172
2173 unsafe extern "C" {
2175 fn cpp_create_unique_list() -> *mut c_void;
2177 fn cpp_destroy_unique_list(list: *mut c_void);
2178 fn cpp_unique_list_push_back(list: *mut c_void, item: *mut c_void);
2179 fn cpp_unique_list_pop_front(list: *mut c_void) -> *mut c_void;
2180 fn cpp_unique_list_is_empty(list: *mut c_void) -> bool;
2181
2182 fn cpp_create_ref_list() -> *mut c_void;
2184 fn cpp_destroy_ref_list(list: *mut c_void);
2185 fn cpp_ref_list_push_back(list: *mut c_void, item: *mut c_void);
2186 fn cpp_ref_list_pop_front(list: *mut c_void) -> *mut c_void;
2187 fn cpp_ref_list_is_empty(list: *mut c_void) -> bool;
2188
2189 fn cpp_create_unique_object(value: i32, destruction_flag: *mut bool) -> *mut c_void;
2191 fn cpp_get_unique_object_value(obj: *mut c_void) -> i32;
2192
2193 fn cpp_create_ref_object(value: i32, destruction_flag: *mut bool) -> *mut c_void;
2195 fn cpp_get_ref_object_value(obj: *mut c_void) -> i32;
2196 }
2197
2198 #[test]
2199 fn test_interop_rust_list_cpp_unique_objects() {
2200 let destroyed1 = AtomicBool::new(false);
2201 let destroyed2 = AtomicBool::new(false);
2202
2203 unsafe {
2204 stack_pin_init!(let list = DoublyLinkedList::<UniquePtr<SharedUniqueObject>>::new());
2205 let list = list.get_unchecked_mut();
2206
2207 let cpp_raw1 = cpp_create_unique_object(1, destroyed1.as_ptr() as *mut bool);
2208 let cpp_raw2 = cpp_create_unique_object(2, destroyed2.as_ptr() as *mut bool);
2209
2210 let obj1 = UniquePtr::from_raw(cpp_raw1 as *mut SharedUniqueObject);
2211 let obj2 = UniquePtr::from_raw(cpp_raw2 as *mut SharedUniqueObject);
2212
2213 list.push_back(obj1);
2214 list.push_back(obj2);
2215
2216 assert!(!destroyed1.load(Ordering::Relaxed));
2217 assert!(!destroyed2.load(Ordering::Relaxed));
2218
2219 let popped = list.pop_front();
2221 assert!(popped.is_some());
2222 assert_eq!(popped.as_ref().unwrap().value, 1);
2223
2224 drop(popped);
2226 assert!(destroyed1.load(Ordering::Relaxed));
2227 assert!(!destroyed2.load(Ordering::Relaxed));
2228
2229 }
2231 assert!(destroyed2.load(Ordering::Relaxed));
2232 }
2233
2234 #[test]
2235 fn test_interop_cpp_list_rust_unique_objects() {
2236 let destroyed1 = Arc::new(AtomicBool::new(false));
2237 let destroyed2 = Arc::new(AtomicBool::new(false));
2238
2239 unsafe {
2240 let cpp_list = cpp_create_unique_list();
2241 assert!(cpp_unique_list_is_empty(cpp_list));
2242
2243 let obj1 = UniquePtr::try_new(SharedUniqueObject::new(1)).unwrap();
2244 let obj2 = UniquePtr::try_new(SharedUniqueObject::new(2)).unwrap();
2245
2246 let raw1 = UniquePtr::as_ptr(&obj1) as *mut SharedUniqueObject;
2248 (*raw1).destruction_flag = destroyed1.as_ptr() as *mut bool;
2249 let raw2 = UniquePtr::as_ptr(&obj2) as *mut SharedUniqueObject;
2250 (*raw2).destruction_flag = destroyed2.as_ptr() as *mut bool;
2251
2252 cpp_unique_list_push_back(cpp_list, UniquePtr::into_raw(obj1) as *mut c_void);
2254 cpp_unique_list_push_back(cpp_list, UniquePtr::into_raw(obj2) as *mut c_void);
2255
2256 assert!(!destroyed1.load(Ordering::Relaxed));
2257 assert!(!destroyed2.load(Ordering::Relaxed));
2258
2259 let popped = cpp_unique_list_pop_front(cpp_list);
2261 assert!(!popped.is_null());
2262 assert_eq!(cpp_get_unique_object_value(popped), 1);
2263
2264 let popped_rust = UniquePtr::from_raw(popped as *mut SharedUniqueObject);
2266 drop(popped_rust);
2267 assert!(destroyed1.load(Ordering::Relaxed));
2268 assert!(!destroyed2.load(Ordering::Relaxed));
2269
2270 cpp_destroy_unique_list(cpp_list);
2272 }
2273 assert!(destroyed2.load(Ordering::Relaxed));
2274 }
2275
2276 #[test]
2277 fn test_interop_rust_list_cpp_ref_objects() {
2278 let destroyed1 = AtomicBool::new(false);
2279 let destroyed2 = AtomicBool::new(false);
2280
2281 unsafe {
2282 stack_pin_init!(let list = DoublyLinkedList::<RefPtr<SharedRefObject>>::new());
2283 let list = list.get_unchecked_mut();
2284
2285 let cpp_raw1 = cpp_create_ref_object(1, destroyed1.as_ptr() as *mut bool);
2286 let cpp_raw2 = cpp_create_ref_object(2, destroyed2.as_ptr() as *mut bool);
2287
2288 let obj1 = RefPtr::from_raw(cpp_raw1 as *mut SharedRefObject);
2289 let obj2 = RefPtr::from_raw(cpp_raw2 as *mut SharedRefObject);
2290
2291 list.push_back(obj1);
2292 list.push_back(obj2);
2293
2294 assert!(!destroyed1.load(Ordering::Relaxed));
2295 assert!(!destroyed2.load(Ordering::Relaxed));
2296
2297 let popped = list.pop_front();
2299 assert!(popped.is_some());
2300 assert_eq!(popped.as_ref().unwrap().value, 1);
2301
2302 drop(popped);
2304 assert!(destroyed1.load(Ordering::Relaxed));
2305 assert!(!destroyed2.load(Ordering::Relaxed));
2306
2307 }
2309 assert!(destroyed2.load(Ordering::Relaxed));
2310 }
2311
2312 #[test]
2313 fn test_interop_cpp_list_rust_ref_objects() {
2314 let destroyed1 = Arc::new(AtomicBool::new(false));
2315 let destroyed2 = Arc::new(AtomicBool::new(false));
2316
2317 unsafe {
2318 let cpp_list = cpp_create_ref_list();
2319 assert!(cpp_ref_list_is_empty(cpp_list));
2320
2321 let obj1 = SharedRefObject::new_ref_counted(1);
2322 let obj2 = SharedRefObject::new_ref_counted(2);
2323
2324 let raw1 = RefPtr::as_ptr(&obj1) as *mut SharedRefObject;
2326 (*raw1).destruction_flag = destroyed1.as_ptr() as *mut bool;
2327 let raw2 = RefPtr::as_ptr(&obj2) as *mut SharedRefObject;
2328 (*raw2).destruction_flag = destroyed2.as_ptr() as *mut bool;
2329
2330 cpp_ref_list_push_back(
2332 cpp_list,
2333 RefPtr::into_raw(obj1) as *mut SharedRefObject as *mut c_void,
2334 );
2335 cpp_ref_list_push_back(
2336 cpp_list,
2337 RefPtr::into_raw(obj2) as *mut SharedRefObject as *mut c_void,
2338 );
2339
2340 assert!(!destroyed1.load(Ordering::Relaxed));
2341 assert!(!destroyed2.load(Ordering::Relaxed));
2342
2343 let popped = cpp_ref_list_pop_front(cpp_list);
2345 assert!(!popped.is_null());
2346 assert_eq!(cpp_get_ref_object_value(popped), 1);
2347
2348 let popped_rust = RefPtr::from_raw(popped as *mut SharedRefObject);
2350 drop(popped_rust);
2351 assert!(destroyed1.load(Ordering::Relaxed));
2352 assert!(!destroyed2.load(Ordering::Relaxed));
2353
2354 cpp_destroy_ref_list(cpp_list);
2356 }
2357 assert!(destroyed2.load(Ordering::Relaxed));
2358 }
2359}