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
77impl<T> Drop for DoublyLinkedListNode<T> {
78 fn drop(&mut self) {
79 debug_assert!(!self.in_container(), "Object destroyed while still in container");
80 }
81}
82
83pub trait DoublyLinkedListContainable<T, Tag = DefaultObjectTag> {
85 fn get_node(&self) -> &DoublyLinkedListNode<T>;
87}
88
89#[repr(C)]
241#[pin_data(PinnedDrop)]
242pub struct DoublyLinkedList<P, Tag = DefaultObjectTag, S = NonTrackingSize>
243where
244 P: PtrTraits,
245 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
246 S: SizeTracker,
247{
248 head: *mut P::Target,
269
270 size: S,
273
274 #[pin]
278 _pin: core::marker::PhantomPinned,
279
280 _phantom: core::marker::PhantomData<(P, Tag)>,
281}
282
283impl<P, Tag, S> DoublyLinkedList<P, Tag, S>
284where
285 P: PtrTraits,
286 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
287 S: SizeTracker,
288{
289 pub fn new() -> impl PinInit<Self, core::convert::Infallible> {
291 pin_init!(&this in Self {
292 head: make_sentinel(this.as_ptr()),
293 size: S::INIT,
294 _pin: core::marker::PhantomPinned,
295 _phantom: core::marker::PhantomData,
296 })
297 }
298
299 fn get_sentinel(&self) -> *mut P::Target {
300 make_sentinel(self as *const Self as *mut Self)
301 }
302
303 fn get_tail(&self) -> *mut P::Target {
304 if self.is_empty() {
305 self.get_sentinel()
306 } else {
307 unsafe { *(*self.head).get_node().prev.get() }
311 }
312 }
313
314 unsafe fn set_tail(&self, tail: *mut P::Target) {
318 debug_assert!(!self.is_empty());
319 unsafe {
323 *(*self.head).get_node().prev.get() = tail;
324 }
325 }
326
327 unsafe fn get_node_ref<'a>(&self, ptr: *mut P::Target) -> &'a DoublyLinkedListNode<P::Target> {
332 let _ = self;
333 unsafe { &(*ptr) }.get_node()
335 }
336
337 pub fn is_empty(&self) -> bool {
339 is_sentinel_ptr(self.head)
340 }
341
342 pub fn front(&self) -> Option<&P::Target> {
344 if self.is_empty() { None } else { unsafe { Some(&*self.head) } }
345 }
346
347 pub fn back(&self) -> Option<&P::Target> {
349 let tail = self.get_tail();
350 if is_sentinel_ptr(tail) { None } else { unsafe { Some(&*tail) } }
351 }
352
353 pub fn push_front(&mut self, ptr: P)
359 where
360 P: ManagedPtr,
361 {
362 unsafe { self.push_front_raw(ptr) }
365 }
366
367 pub unsafe fn push_front_raw(&mut self, ptr: P) {
378 let head = self.head;
379 let mut cursor = CursorMut { list: self, current: head };
380 unsafe {
382 cursor.insert_before_raw(ptr);
383 }
384 }
385
386 pub fn push_back(&mut self, ptr: P)
392 where
393 P: ManagedPtr,
394 {
395 unsafe { self.push_back_raw(ptr) }
398 }
399
400 pub unsafe fn push_back_raw(&mut self, ptr: P) {
411 let sentinel = self.get_sentinel();
412 let mut cursor = CursorMut { list: self, current: sentinel };
413 unsafe {
415 cursor.insert_before_raw(ptr);
416 }
417 }
418
419 pub fn pop_front(&mut self) -> Option<P> {
421 if self.is_empty() {
422 return None;
423 }
424 let head = self.head;
425 let mut cursor = CursorMut { list: self, current: head };
426 cursor.erase()
427 }
428
429 pub fn pop_back(&mut self) -> Option<P> {
431 if self.is_empty() {
432 return None;
433 }
434 let tail = self.get_tail();
435 let mut cursor = CursorMut { list: self, current: tail };
436 cursor.erase()
437 }
438
439 pub fn clear(&mut self) {
441 while let Some(_) = self.pop_front() {}
442 }
443
444 pub unsafe fn erase(&mut self, obj: &P::Target) -> Option<P> {
451 let ptr = obj as *const P::Target as *mut P::Target;
452 let node = obj.get_node();
453
454 if !node.in_container() {
455 return None;
456 }
457
458 let mut cursor = self.cursor_mut();
459 cursor.current = ptr;
460 cursor.erase()
461 }
462
463 pub unsafe fn replace_raw(&mut self, obj: &P::Target, replacement: P) -> Option<P> {
470 let ptr = obj as *const P::Target as *mut P::Target;
471 let node = obj.get_node();
472
473 if !node.in_container() {
474 return None;
475 }
476
477 let mut cursor = self.cursor_mut();
478 cursor.current = ptr;
479 unsafe { cursor.replace_raw(replacement) }
481 }
482
483 pub fn erase_if<F>(&mut self, mut f: F) -> Option<P>
486 where
487 F: FnMut(&P::Target) -> bool,
488 {
489 let mut cursor = self.cursor_mut();
490 while let Some(item) = cursor.get() {
491 if f(item) {
492 return cursor.erase();
493 } else {
494 cursor.move_next();
495 }
496 }
497 None
498 }
499
500 pub fn find_if<F>(&self, mut f: F) -> Option<&P::Target>
502 where
503 F: FnMut(&P::Target) -> bool,
504 {
505 self.iter().find(|&x| f(x))
506 }
507
508 pub fn cursor_mut(&mut self) -> CursorMut<'_, P, Tag, S> {
510 let head = self.head;
511 CursorMut { list: self, current: head }
512 }
513
514 pub unsafe fn cursor_at(&mut self, obj: &P::Target) -> CursorMut<'_, P, Tag, S> {
522 assert!(obj.get_node().in_container(), "Object must be in a container");
523 CursorMut { list: self, current: obj as *const P::Target as *mut P::Target }
524 }
525
526 pub fn iter(&self) -> Iterator<'_, P, Tag> {
527 Iterator::new(self)
528 }
529
530 pub fn forward_iter(&self) -> ForwardIterator<'_, P, Tag> {
532 ForwardIterator::new(self.head)
533 }
534
535 pub fn reverse_iter(&self) -> ReverseIterator<'_, P, Tag> {
537 ReverseIterator::new(self.get_tail())
538 }
539}
540
541impl<P, Tag> DoublyLinkedList<P, Tag, TrackingSize>
542where
543 P: PtrTraits,
544 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
545{
546 pub fn len(&self) -> usize {
548 self.size.get()
549 }
550}
551
552#[pinned_drop]
553impl<P, Tag, S> PinnedDrop for DoublyLinkedList<P, Tag, S>
554where
555 P: PtrTraits,
556 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
557 S: SizeTracker,
558{
559 fn drop(self: Pin<&mut Self>) {
560 if P::IS_MANAGED {
561 let me = unsafe { self.get_unchecked_mut() };
563 me.clear();
564 } else {
565 debug_assert!(self.is_empty(), "List must be empty on destruction");
566 if S::IS_TRACKING {
567 debug_assert_eq!(self.size.get(), 0, "Size must be zero on destruction");
568 }
569 }
570 }
571}
572
573pub struct CursorMut<'a, P, Tag = DefaultObjectTag, S = NonTrackingSize>
575where
576 P: PtrTraits,
577 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
578 S: SizeTracker,
579{
580 list: &'a mut DoublyLinkedList<P, Tag, S>,
581 current: *mut P::Target,
582}
583
584impl<'a, P, Tag, S> CursorMut<'a, P, Tag, S>
585where
586 P: PtrTraits,
587 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
588 S: SizeTracker,
589{
590 pub fn get(&self) -> Option<&P::Target> {
591 if is_sentinel_ptr(self.current) { None } else { unsafe { Some(&*self.current) } }
592 }
593
594 pub fn get_mut(&mut self) -> Option<&mut P::Target> {
595 if is_sentinel_ptr(self.current) { None } else { unsafe { Some(&mut *self.current) } }
596 }
597
598 pub fn move_next(&mut self) {
599 if !is_sentinel_ptr(self.current) {
600 let node = unsafe { self.list.get_node_ref(self.current) };
602 self.current = node.get_next();
603 }
604 }
605
606 pub fn move_prev(&mut self) {
607 if !is_sentinel_ptr(self.current) {
608 let node = unsafe { self.list.get_node_ref(self.current) };
610 let prev = node.get_prev();
611 if self.current == self.list.head {
612 self.current = self.list.get_sentinel(); } else {
614 self.current = prev;
615 }
616 } else {
617 self.current = self.list.get_tail();
619 }
620 }
621
622 pub fn insert_after(&mut self, ptr: P)
629 where
630 P: ManagedPtr,
631 {
632 unsafe { self.insert_after_raw(ptr) }
636 }
637
638 pub unsafe fn insert_after_raw(&mut self, ptr: P) {
649 assert!(!is_sentinel_ptr(self.current), "Cannot insert after end sentinel");
650 let raw = P::into_raw(ptr);
651 let node = unsafe { self.list.get_node_ref(raw) };
653 assert!(!node.in_container());
654
655 let current_node = unsafe { self.list.get_node_ref(self.current) };
657 let next = current_node.get_next();
658
659 let current_save = self.current;
660 self.current = next;
661 unsafe {
664 self.insert_chain_before(raw, raw, 1);
665 }
666 self.current = current_save;
667 }
668
669 pub fn replace(&mut self, replacement: P) -> Option<P>
676 where
677 P: ManagedPtr,
678 {
679 unsafe { self.replace_raw(replacement) }
682 }
683
684 pub unsafe fn replace_raw(&mut self, replacement: P) -> Option<P> {
696 if is_sentinel_ptr(self.current) {
697 return None;
698 }
699 unsafe {
702 self.insert_before_raw(replacement);
703 }
704 self.erase()
705 }
706
707 pub fn insert_before(&mut self, ptr: P)
713 where
714 P: ManagedPtr,
715 {
716 unsafe { self.insert_before_raw(ptr) }
719 }
720
721 pub unsafe fn insert_before_raw(&mut self, ptr: P) {
732 let raw = P::into_raw(ptr);
733 let node = unsafe { self.list.get_node_ref(raw) };
735 assert!(!node.in_container());
736
737 unsafe {
739 self.insert_chain_before(raw, raw, 1);
740 }
741 }
742
743 unsafe fn insert_chain_before(
754 &mut self,
755 chain_head: *mut P::Target,
756 chain_tail: *mut P::Target,
757 count: usize,
758 ) {
759 let chain_tail_node = unsafe { self.list.get_node_ref(chain_tail) };
761 chain_tail_node.set_next(self.current);
762
763 if self.list.is_empty() {
764 let chain_head_node = unsafe { self.list.get_node_ref(chain_head) };
766 chain_head_node.set_prev(chain_tail);
767 self.list.head = chain_head;
768 } else {
769 let prev = if self.current == self.list.head || is_sentinel_ptr(self.current) {
770 self.list.get_tail()
771 } else {
772 let current_node = unsafe { self.list.get_node_ref(self.current) };
774 current_node.get_prev()
775 };
776
777 let chain_head_node = unsafe { self.list.get_node_ref(chain_head) };
779 chain_head_node.set_prev(prev);
780
781 if self.current != self.list.head {
783 let prev_node = unsafe { self.list.get_node_ref(prev) };
785 prev_node.set_next(chain_head);
786 }
787
788 if !is_sentinel_ptr(self.current) {
790 let current_node = unsafe { self.list.get_node_ref(self.current) };
792 current_node.set_prev(chain_tail);
793 }
794
795 if self.current == self.list.head {
797 self.list.head = chain_head;
798 }
799
800 if is_sentinel_ptr(self.current) {
802 unsafe {
804 self.list.set_tail(chain_tail);
805 }
806 }
807 }
808
809 if S::IS_TRACKING {
810 self.list.size.set(self.list.size.get() + count);
811 }
812 }
813
814 pub fn splice(&mut self, other: &mut DoublyLinkedList<P, Tag, S>) {
828 if other.is_empty() {
829 return;
830 }
831
832 let other_head = other.head;
833 let other_tail = other.get_tail();
834 let count = if S::IS_TRACKING { other.size.get() } else { 0 };
835
836 unsafe {
839 self.insert_chain_before(other_head, other_tail, count);
840 }
841
842 other.head = other.get_sentinel();
843 if S::IS_TRACKING {
844 other.size.set(0);
845 }
846 }
847
848 pub fn erase(&mut self) -> Option<P> {
849 if is_sentinel_ptr(self.current) {
850 return None;
851 }
852 let ptr = self.current;
853 let node = unsafe { self.list.get_node_ref(ptr) };
855 let next = node.get_next();
856 let prev = node.get_prev();
857
858 self.list.size.decrement();
859
860 if self.list.head == ptr && is_sentinel_ptr(next) {
861 self.list.head = self.list.get_sentinel();
862 } else {
863 if self.current != self.list.head {
865 let prev_node = unsafe { self.list.get_node_ref(prev) };
867 prev_node.set_next(next);
868 }
869
870 if !is_sentinel_ptr(next) {
872 let next_node = unsafe { self.list.get_node_ref(next) };
874 next_node.set_prev(prev);
875 }
876
877 if self.current == self.list.head {
879 self.list.head = next;
880 }
881
882 if is_sentinel_ptr(next) {
884 unsafe {
886 self.list.set_tail(prev);
887 }
888 }
889 }
890
891 node.set_next(core::ptr::null_mut());
892 node.set_prev(core::ptr::null_mut());
893
894 self.current = next;
895 Some(unsafe { P::from_raw(ptr) })
897 }
898}
899
900pub struct Iterator<'a, P, Tag = DefaultObjectTag>
902where
903 P: PtrTraits,
904 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
905{
906 front: ForwardIterator<'a, P, Tag>,
907 back: ReverseIterator<'a, P, Tag>,
908}
909
910impl<'a, P, Tag> Iterator<'a, P, Tag>
911where
912 P: PtrTraits,
913 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
914{
915 fn new<S: SizeTracker>(list: &'a DoublyLinkedList<P, Tag, S>) -> Self {
916 if list.is_empty() {
917 Self {
918 front: ForwardIterator::new(crate::make_sentinel_null()),
919 back: ReverseIterator::new(crate::make_sentinel_null()),
920 }
921 } else {
922 Self {
923 front: ForwardIterator::new(list.head),
924 back: ReverseIterator::new(list.get_tail()),
925 }
926 }
927 }
928}
929
930impl<'a, P, Tag> core::iter::Iterator for Iterator<'a, P, Tag>
931where
932 P: PtrTraits,
933 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
934{
935 type Item = &'a P::Target;
936
937 fn next(&mut self) -> Option<Self::Item> {
938 let met = self.front.current == self.back.current;
939 let item = self.front.next();
940 if item.is_some() {
941 if met {
942 self.front.current = crate::make_sentinel_null();
943 self.back.current = crate::make_sentinel_null();
944 }
945 }
946 item
947 }
948}
949
950impl<'a, P, Tag> core::iter::DoubleEndedIterator for Iterator<'a, P, Tag>
951where
952 P: PtrTraits,
953 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
954{
955 fn next_back(&mut self) -> Option<Self::Item> {
956 let met = self.front.current == self.back.current;
957 let item = self.back.next();
958 if item.is_some() {
959 if met {
960 self.front.current = crate::make_sentinel_null();
961 self.back.current = crate::make_sentinel_null();
962 }
963 }
964 item
965 }
966}
967
968pub struct ForwardIterator<'a, P, Tag = DefaultObjectTag>
970where
971 P: PtrTraits,
972 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
973{
974 current: *mut P::Target,
975 _phantom: core::marker::PhantomData<&'a (P, Tag)>,
976}
977
978impl<'a, P, Tag> ForwardIterator<'a, P, Tag>
979where
980 P: PtrTraits,
981 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
982{
983 fn new(current: *mut P::Target) -> Self {
984 Self { current, _phantom: core::marker::PhantomData }
985 }
986
987 pub fn from_element(obj: &'a P::Target) -> Self {
993 assert!(obj.get_node().in_container(), "Object must be in a container");
994 Self { current: obj as *const _ as *mut _, _phantom: core::marker::PhantomData }
995 }
996}
997
998impl<'a, P, Tag> core::iter::Iterator for ForwardIterator<'a, P, Tag>
999where
1000 P: PtrTraits,
1001 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1002{
1003 type Item = &'a P::Target;
1004
1005 fn next(&mut self) -> Option<Self::Item> {
1006 if is_sentinel_ptr(self.current) {
1007 None
1008 } else {
1009 let current = unsafe { &*self.current };
1013 self.current = current.get_node().get_next();
1014 Some(current)
1015 }
1016 }
1017}
1018
1019pub struct ReverseIterator<'a, P, Tag = DefaultObjectTag>
1021where
1022 P: PtrTraits,
1023 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1024{
1025 current: *mut P::Target,
1026 _phantom: core::marker::PhantomData<&'a (P, Tag)>,
1027}
1028
1029impl<'a, P, Tag> ReverseIterator<'a, P, Tag>
1030where
1031 P: PtrTraits,
1032 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1033{
1034 fn new(current: *mut P::Target) -> Self {
1035 Self { current, _phantom: core::marker::PhantomData }
1036 }
1037
1038 pub fn from_element(obj: &'a P::Target) -> Self {
1044 assert!(obj.get_node().in_container(), "Object must be in a container");
1045 Self { current: obj as *const _ as *mut _, _phantom: core::marker::PhantomData }
1046 }
1047}
1048
1049impl<'a, P, Tag> core::iter::Iterator for ReverseIterator<'a, P, Tag>
1050where
1051 P: PtrTraits,
1052 P::Target: DoublyLinkedListContainable<P::Target, Tag>,
1053{
1054 type Item = &'a P::Target;
1055
1056 fn next(&mut self) -> Option<Self::Item> {
1057 if is_sentinel_ptr(self.current) {
1058 None
1059 } else {
1060 let current = unsafe { &*self.current };
1064 let prev = current.get_node().get_prev();
1065
1066 let prev_node = unsafe { &*prev }.get_node();
1069 if is_sentinel_ptr(prev_node.get_next()) {
1070 self.current = prev_node.get_next();
1073 } else {
1074 self.current = prev;
1075 }
1076 Some(current)
1077 }
1078 }
1079}
1080
1081pub unsafe fn remove_from_container<T, Tag, P>(obj: &T) -> Option<P>
1089where
1090 P: PtrTraits<Target = T>,
1091 T: DoublyLinkedListContainable<T, Tag>,
1092{
1093 let node = obj.get_node();
1094 if !node.in_container() {
1095 return None;
1096 }
1097
1098 let mut current = obj as *const T as *mut T;
1099 unsafe {
1100 while !is_sentinel_ptr(current) {
1101 current = (*current).get_node().get_next();
1102 }
1103
1104 let list_ptr = crate::sentinel::unmake_sentinel::<
1105 DoublyLinkedList<P, Tag, NonTrackingSize>,
1106 T,
1107 >(current);
1108 let list_ref = &mut *list_ptr;
1109
1110 list_ref.erase(obj)
1111 }
1112}
1113
1114impl<P, Tag, S> core::fmt::Debug for DoublyLinkedList<P, Tag, S>
1115where
1116 P: PtrTraits,
1117 P::Target: DoublyLinkedListContainable<P::Target, Tag> + core::fmt::Debug,
1118 S: SizeTracker,
1119{
1120 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1121 f.debug_list().entries(self.iter()).finish()
1122 }
1123}
1124
1125#[cfg(test)]
1126mod tests {
1127 extern crate alloc;
1128 use super::*;
1129 use crate::intrusive_container_test_support::*;
1130 use crate::ref_ptr::RefPtr;
1131 use crate::unique_ptr::UniquePtr;
1132 use core::ffi::c_void;
1133 use pin_init::stack_pin_init;
1134
1135 #[derive(crate::DoublyLinkedListContainable, crate::Recyclable)]
1136 struct TestObject {
1137 value: i32,
1138 #[dll_node]
1139 node: DoublyLinkedListNode<TestObject>,
1140 }
1141
1142 impl TestObject {
1143 fn new(value: i32) -> Self {
1144 Self { value, node: DoublyLinkedListNode::new() }
1145 }
1146 }
1147
1148 impl TestValue for TestObject {
1149 fn new(value: i32) -> Self {
1150 Self::new(value)
1151 }
1152 }
1153
1154 ::zr::static_assert!(
1155 core::mem::size_of::<DoublyLinkedList<*mut TestObject>>()
1156 == core::mem::size_of::<*mut TestObject>()
1157 );
1158 ::zr::static_assert!(
1159 core::mem::align_of::<DoublyLinkedList<*mut TestObject>>()
1160 == core::mem::align_of::<*mut TestObject>()
1161 );
1162
1163 ::zr::static_assert!(
1164 core::mem::size_of::<DoublyLinkedList<*mut TestObject, DefaultObjectTag, TrackingSize>>()
1165 == 2 * core::mem::size_of::<*mut TestObject>()
1166 );
1167 ::zr::static_assert!(
1168 core::mem::align_of::<DoublyLinkedList<*mut TestObject, DefaultObjectTag, TrackingSize>>()
1169 == core::mem::align_of::<*mut TestObject>()
1170 );
1171
1172 ::zr::static_assert!(
1173 core::mem::size_of::<ForwardIterator<'_, *mut TestObject>>()
1174 == core::mem::size_of::<*mut TestObject>()
1175 );
1176 ::zr::static_assert!(
1177 core::mem::align_of::<ForwardIterator<'_, *mut TestObject>>()
1178 == core::mem::align_of::<*mut TestObject>()
1179 );
1180
1181 ::zr::static_assert!(
1182 core::mem::size_of::<ReverseIterator<'_, *mut TestObject>>()
1183 == core::mem::size_of::<*mut TestObject>()
1184 );
1185 ::zr::static_assert!(
1186 core::mem::align_of::<ReverseIterator<'_, *mut TestObject>>()
1187 == core::mem::align_of::<*mut TestObject>()
1188 );
1189
1190 #[derive(crate::DoublyLinkedListContainable, crate::Recyclable)]
1191 struct UniqueTestObject {
1192 value: i32,
1193 #[dll_node]
1194 node: DoublyLinkedListNode<UniqueTestObject>,
1195 }
1196
1197 impl UniqueTestObject {
1198 fn new(value: i32) -> Self {
1199 Self { value, node: DoublyLinkedListNode::new() }
1200 }
1201 }
1202
1203 impl TestValue for UniqueTestObject {
1204 fn new(value: i32) -> Self {
1205 Self::new(value)
1206 }
1207 }
1208
1209 #[fbl::ref_counted]
1210 #[derive(crate::DoublyLinkedListContainable, crate::Recyclable)]
1211 #[repr(C)]
1212 pub struct RefTestObject {
1213 value: i32,
1214 #[dll_node]
1215 node: DoublyLinkedListNode<RefTestObject>,
1216 }
1217
1218 impl TestValue for RefTestObject {
1219 fn new_ref_counted(value: i32) -> RefPtr<Self> {
1220 crate::make_ref_counted!(RefTestObject {
1221 value: value,
1222 node: DoublyLinkedListNode::new()
1223 })
1224 .unwrap()
1225 }
1226 }
1227
1228 macro_rules! generate_list_tests {
1229 ($mod_name:ident, $ptr_type:ty, $factory_type:ty, $get_val:expr, $push:expr) => {
1230 mod $mod_name {
1231 use super::*;
1232
1233 #[test]
1234 fn test_basic() {
1235 let mut factory = <$factory_type>::new();
1236 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1237 let list = unsafe { list.get_unchecked_mut() };
1238 assert!(list.is_empty());
1239
1240 let obj1 = factory.create(1);
1241 let obj2 = factory.create(2);
1242
1243 $push(list, obj1);
1244 $push(list, obj2);
1245
1246 assert!(!list.is_empty());
1247
1248 let mut iter = list.iter();
1249 assert_eq!(iter.next().unwrap().value, 2);
1250 assert_eq!(iter.next().unwrap().value, 1);
1251 assert!(iter.next().is_none());
1252
1253 list.clear();
1254 assert!(list.is_empty());
1255 }
1256
1257 #[test]
1258 fn test_double_ended_iterator() {
1259 let mut factory = <$factory_type>::new();
1260 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1261 let list = unsafe { list.get_unchecked_mut() };
1262 let obj1 = factory.create(1);
1263 let obj2 = factory.create(2);
1264 let obj3 = factory.create(3);
1265
1266 $push(list, obj1);
1267 $push(list, obj2);
1268 $push(list, obj3);
1269
1270 let mut iter = list.iter();
1271 assert_eq!(iter.next().unwrap().value, 3);
1272 assert_eq!(iter.next_back().unwrap().value, 1);
1273 assert_eq!(iter.next().unwrap().value, 2);
1274 assert!(iter.next().is_none());
1275 assert!(iter.next_back().is_none());
1276
1277 list.clear();
1278 }
1279
1280 #[test]
1281 fn test_explicit_pops() {
1282 let mut factory = <$factory_type>::new();
1283 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1284 let list = unsafe { list.get_unchecked_mut() };
1285 let obj1 = factory.create(1);
1286 let obj2 = factory.create(2);
1287
1288 $push(list, obj1);
1289 $push(list, obj2);
1290
1291 let p1 = list.pop_front();
1292 assert!(p1.is_some());
1293 let p2 = list.pop_front();
1294 assert!(p2.is_some());
1295 assert!(list.pop_front().is_none());
1296 }
1297
1298 #[test]
1299 fn test_cursor_move_prev() {
1300 let mut factory = <$factory_type>::new();
1301 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1302 let list = unsafe { list.get_unchecked_mut() };
1303 let obj1 = factory.create(1);
1304 let obj2 = factory.create(2);
1305 let obj3 = factory.create(3);
1306
1307 $push(list, obj1);
1308 $push(list, obj2);
1309 $push(list, obj3);
1310
1311 let (a, b, c) = {
1312 let mut iter = list.iter();
1313 (
1314 $get_val(iter.next().unwrap()),
1315 $get_val(iter.next().unwrap()),
1316 $get_val(iter.next().unwrap()),
1317 )
1318 };
1319
1320 let mut cursor = list.cursor_mut();
1321 assert_eq!($get_val(cursor.get().unwrap()), a);
1322
1323 cursor.move_prev();
1324 assert!(cursor.get().is_none()); cursor.move_prev();
1327 assert_eq!($get_val(cursor.get().unwrap()), c);
1328
1329 cursor.move_prev();
1330 assert_eq!($get_val(cursor.get().unwrap()), b);
1331
1332 cursor.move_prev();
1333 assert_eq!($get_val(cursor.get().unwrap()), a);
1334
1335 list.clear();
1336 }
1337
1338 #[test]
1339 fn test_cursor_insert_after() {
1340 let mut factory = <$factory_type>::new();
1341 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1342 let list = unsafe { list.get_unchecked_mut() };
1343 let obj1 = factory.create(1);
1344 let obj2 = factory.create(2);
1345 let obj3 = factory.create(3);
1346
1347 $push(list, obj1);
1348
1349 let mut cursor = list.cursor_mut();
1350 unsafe {
1351 cursor.insert_after_raw(obj3);
1352 cursor.insert_after_raw(obj2);
1353 }
1354
1355 let mut iter = list.iter();
1356 assert_eq!($get_val(iter.next().unwrap()), 1);
1357 assert_eq!($get_val(iter.next().unwrap()), 2);
1358 assert_eq!($get_val(iter.next().unwrap()), 3);
1359 assert!(iter.next().is_none());
1360
1361 list.clear();
1362 }
1363
1364 #[test]
1365 fn test_pop_back() {
1366 let mut factory = <$factory_type>::new();
1367 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1368 let list = unsafe { list.get_unchecked_mut() };
1369 let obj1 = factory.create(1);
1370 let obj2 = factory.create(2);
1371
1372 $push(list, obj1);
1373 $push(list, obj2);
1374
1375 let p1 = list.pop_back();
1376 assert!(p1.is_some());
1377 let p2 = list.pop_back();
1378 assert!(p2.is_some());
1379 assert!(list.pop_back().is_none());
1380 }
1381
1382 #[test]
1383 fn test_erase() {
1384 let mut factory = <$factory_type>::new();
1385 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1386 let list = unsafe { list.get_unchecked_mut() };
1387 let obj1 = factory.create(1);
1388 let obj2 = factory.create(2);
1389 let obj3 = factory.create(3);
1390
1391 $push(list, obj1);
1392 $push(list, obj2);
1393 $push(list, obj3);
1394
1395 let mut cursor = list.cursor_mut();
1396 cursor.move_next();
1397 let erased = cursor.erase();
1398 assert!(erased.is_some());
1399 factory.cleanup(erased.unwrap());
1400
1401 let mut iter = list.iter();
1402 assert!(iter.next().is_some());
1403 assert!(iter.next().is_some());
1404 assert!(iter.next().is_none());
1405
1406 list.clear();
1407 }
1408
1409 #[test]
1410 fn test_erase_if() {
1411 let mut factory = <$factory_type>::new();
1412 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1413 let list = unsafe { list.get_unchecked_mut() };
1414 let obj1 = factory.create(1);
1415 let obj2 = factory.create(2);
1416 let obj3 = factory.create(3);
1417
1418 $push(list, obj1);
1419 $push(list, obj2);
1420 $push(list, obj3);
1421
1422 let erased = list.erase_if(|o| o.value == 2);
1423 assert!(erased.is_some());
1424 assert_eq!($get_val(erased.unwrap().get_ref()), 2);
1425
1426 let mut iter = list.iter();
1427 assert_eq!($get_val(iter.next().unwrap()), 3);
1428 assert_eq!($get_val(iter.next().unwrap()), 1);
1429 assert!(iter.next().is_none());
1430
1431 list.clear();
1432 }
1433
1434 #[test]
1435 fn test_find_if() {
1436 let mut factory = <$factory_type>::new();
1437 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1438 let list = unsafe { list.get_unchecked_mut() };
1439 let obj1 = factory.create(1);
1440 let obj2 = factory.create(2);
1441
1442 $push(list, obj1);
1443 $push(list, obj2);
1444
1445 let found = list.find_if(|o| o.value == 1);
1446 assert!(found.is_some());
1447 assert_eq!(found.unwrap().value, 1);
1448
1449 let found = list.find_if(|o| o.value == 3);
1450 assert!(found.is_none());
1451
1452 list.clear();
1453 }
1454
1455 #[test]
1456 fn test_complete_reverse_iteration() {
1457 let mut factory = <$factory_type>::new();
1458 stack_pin_init!(let list = DoublyLinkedList::<$ptr_type>::new());
1459 let list = unsafe { list.get_unchecked_mut() };
1460 let obj1 = factory.create(1);
1461 let obj2 = factory.create(2);
1462 let obj3 = factory.create(3);
1463
1464 $push(list, obj1);
1465 $push(list, obj2);
1466 $push(list, obj3);
1467
1468 let (a, b, c) = {
1469 let mut iter = list.iter();
1470 (
1471 $get_val(iter.next().unwrap()),
1472 $get_val(iter.next().unwrap()),
1473 $get_val(iter.next().unwrap()),
1474 )
1475 };
1476
1477 let mut iter = list.iter();
1478 assert_eq!($get_val(iter.next_back().unwrap()), c);
1479 assert_eq!($get_val(iter.next_back().unwrap()), b);
1480 assert_eq!($get_val(iter.next_back().unwrap()), a);
1481 assert!(iter.next_back().is_none());
1482
1483 list.clear();
1484 }
1485 }
1486 };
1487 }
1488
1489 generate_list_tests!(
1490 raw_ptr_tests,
1491 *mut TestObject,
1492 RawFactory<TestObject>,
1493 |p: &TestObject| p.value,
1494 |list: &mut DoublyLinkedList<*mut TestObject>, obj| unsafe {
1495 list.push_front_raw(obj);
1496 }
1497 );
1498
1499 generate_list_tests!(
1500 unique_ptr_tests,
1501 UniquePtr<UniqueTestObject>,
1502 UniqueFactory<UniqueTestObject>,
1503 |p: &UniqueTestObject| p.value,
1504 |list: &mut DoublyLinkedList<UniquePtr<UniqueTestObject>>, obj| list.push_front(obj)
1505 );
1506
1507 generate_list_tests!(
1508 ref_ptr_tests,
1509 RefPtr<RefTestObject>,
1510 RefFactory<RefTestObject>,
1511 |p: &RefTestObject| p.value,
1512 |list: &mut DoublyLinkedList<RefPtr<RefTestObject>>, obj| list.push_front(obj)
1513 );
1514
1515 #[test]
1516 fn test_tracking_size() {
1517 stack_pin_init!(let list =
1518 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1519 let list = unsafe { list.get_unchecked_mut() };
1520
1521 assert_eq!(list.len(), 0);
1522 list.push_front(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1523 assert_eq!(list.len(), 1);
1524 list.push_front(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1525 assert_eq!(list.len(), 2);
1526 list.pop_front();
1527 assert_eq!(list.len(), 1);
1528 list.clear();
1529 assert_eq!(list.len(), 0);
1530 }
1531
1532 #[test]
1533 fn test_insert_before() {
1534 stack_pin_init!(let list =
1535 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1536 let list = unsafe { list.get_unchecked_mut() };
1537
1538 let mut cursor = list.cursor_mut();
1539 cursor.insert_before(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1540 assert_eq!(list.len(), 1);
1541 assert_eq!(list.front().unwrap().value, 1);
1542
1543 let mut cursor = list.cursor_mut();
1544 cursor.insert_before(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1545 assert_eq!(list.len(), 2);
1546 assert_eq!(list.front().unwrap().value, 2);
1547
1548 let mut cursor = list.cursor_mut();
1549 cursor.move_next(); cursor.insert_before(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1551 assert_eq!(list.len(), 3);
1552
1553 let mut cursor = list.cursor_mut();
1554 while cursor.get().unwrap().value != 1 {
1555 cursor.move_next();
1556 }
1557 cursor.move_next(); cursor.insert_before(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
1559 assert_eq!(list.len(), 4);
1560
1561 let mut iter = list.iter();
1562 assert_eq!(iter.next().unwrap().value, 2);
1563 assert_eq!(iter.next().unwrap().value, 3);
1564 assert_eq!(iter.next().unwrap().value, 1);
1565 assert_eq!(iter.next().unwrap().value, 4);
1566 assert!(iter.next().is_none());
1567
1568 list.clear();
1569 }
1570
1571 #[test]
1572 fn test_splice_middle() {
1573 stack_pin_init!(let list1 =
1574 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1575 let list1 = unsafe { list1.get_unchecked_mut() };
1576 stack_pin_init!(let list2 =
1577 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1578 let list2 = unsafe { list2.get_unchecked_mut() };
1579
1580 list1.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1581 list1.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1582 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1583 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
1584
1585 let mut cursor = list1.cursor_mut();
1586 cursor.move_next(); cursor.splice(list2);
1589
1590 assert!(list2.is_empty());
1591 assert_eq!(list1.len(), 4);
1592
1593 let mut iter = list1.iter();
1594 assert_eq!(iter.next().unwrap().value, 1);
1595 assert_eq!(iter.next().unwrap().value, 3);
1596 assert_eq!(iter.next().unwrap().value, 4);
1597 assert_eq!(iter.next().unwrap().value, 2);
1598 assert!(iter.next().is_none());
1599
1600 list1.clear();
1601 }
1602
1603 #[test]
1604 fn test_splice_head() {
1605 stack_pin_init!(let list1 =
1606 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1607 let list1 = unsafe { list1.get_unchecked_mut() };
1608 stack_pin_init!(let list2 =
1609 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1610 let list2 = unsafe { list2.get_unchecked_mut() };
1611
1612 list1.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1613 list1.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1614 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1615 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
1616
1617 let mut cursor = list1.cursor_mut();
1618
1619 cursor.splice(list2);
1620
1621 assert!(list2.is_empty());
1622 assert_eq!(list1.len(), 4);
1623
1624 let mut iter = list1.iter();
1625 assert_eq!(iter.next().unwrap().value, 3);
1626 assert_eq!(iter.next().unwrap().value, 4);
1627 assert_eq!(iter.next().unwrap().value, 1);
1628 assert_eq!(iter.next().unwrap().value, 2);
1629 assert!(iter.next().is_none());
1630
1631 list1.clear();
1632 }
1633
1634 #[test]
1635 fn test_splice_tail() {
1636 stack_pin_init!(let list1 =
1637 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1638 let list1 = unsafe { list1.get_unchecked_mut() };
1639 stack_pin_init!(let list2 =
1640 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1641 let list2 = unsafe { list2.get_unchecked_mut() };
1642
1643 list1.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1644 list1.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1645 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1646 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
1647
1648 let mut cursor = list1.cursor_mut();
1649 cursor.move_next();
1650 cursor.move_next(); cursor.splice(list2);
1653
1654 assert!(list2.is_empty());
1655 assert_eq!(list1.len(), 4);
1656
1657 let mut iter = list1.iter();
1658 assert_eq!(iter.next().unwrap().value, 1);
1659 assert_eq!(iter.next().unwrap().value, 2);
1660 assert_eq!(iter.next().unwrap().value, 3);
1661 assert_eq!(iter.next().unwrap().value, 4);
1662 assert!(iter.next().is_none());
1663
1664 list1.clear();
1665 }
1666
1667 #[test]
1668 fn test_splice_empty() {
1669 stack_pin_init!(let list1 =
1670 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1671 let list1 = unsafe { list1.get_unchecked_mut() };
1672 stack_pin_init!(let list2 =
1673 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1674 let list2 = unsafe { list2.get_unchecked_mut() };
1675
1676 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1677 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1678
1679 let mut cursor = list1.cursor_mut();
1680 cursor.splice(list2);
1681
1682 assert!(list2.is_empty());
1683 assert_eq!(list1.len(), 2);
1684
1685 let mut iter = list1.iter();
1686 assert_eq!(iter.next().unwrap().value, 1);
1687 assert_eq!(iter.next().unwrap().value, 2);
1688 assert!(iter.next().is_none());
1689
1690 list1.clear();
1691 }
1692
1693 #[test]
1694 fn test_splice_non_tracking() {
1695 stack_pin_init!(let list1 =
1696 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, NonTrackingSize>::new());
1697 let list1 = unsafe { list1.get_unchecked_mut() };
1698 stack_pin_init!(let list2 =
1699 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, NonTrackingSize>::new());
1700 let list2 = unsafe { list2.get_unchecked_mut() };
1701
1702 list1.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1703 list1.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1704 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1705 list2.push_back(UniquePtr::try_new(UniqueTestObject::new(4)).unwrap());
1706
1707 let mut cursor = list1.cursor_mut();
1708 cursor.move_next(); cursor.splice(list2);
1711
1712 assert!(list2.is_empty());
1713
1714 let mut iter = list1.iter();
1715 assert_eq!(iter.next().unwrap().value, 1);
1716 assert_eq!(iter.next().unwrap().value, 3);
1717 assert_eq!(iter.next().unwrap().value, 4);
1718 assert_eq!(iter.next().unwrap().value, 2);
1719 assert!(iter.next().is_none());
1720
1721 list1.clear();
1722 }
1723
1724 #[test]
1725 fn test_pop_back() {
1726 stack_pin_init!(let list =
1727 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1728 let list = unsafe { list.get_unchecked_mut() };
1729
1730 list.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1731 list.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1732
1733 assert_eq!(list.len(), 2);
1734 let popped = list.pop_back();
1735 assert!(popped.is_some());
1736 assert_eq!(popped.unwrap().value, 2);
1737 assert_eq!(list.len(), 1);
1738
1739 let popped = list.pop_back();
1740 assert!(popped.is_some());
1741 assert_eq!(popped.unwrap().value, 1);
1742 assert_eq!(list.len(), 0);
1743
1744 assert!(list.pop_back().is_none());
1745 }
1746
1747 #[test]
1748 fn test_erase() {
1749 stack_pin_init!(let list =
1750 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1751 let list = unsafe { list.get_unchecked_mut() };
1752
1753 list.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1754 list.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1755 list.push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1756
1757 assert_eq!(list.len(), 3);
1758
1759 let mut cursor = list.cursor_mut();
1761 cursor.move_next(); let erased = cursor.erase();
1763 assert!(erased.is_some());
1764 assert_eq!(erased.unwrap().value, 2);
1765 assert_eq!(list.len(), 2);
1766
1767 let mut iter = list.iter();
1768 assert_eq!(iter.next().unwrap().value, 1);
1769 assert_eq!(iter.next().unwrap().value, 3);
1770 assert!(iter.next().is_none());
1771
1772 let mut cursor = list.cursor_mut();
1774 let erased = cursor.erase(); assert!(erased.is_some());
1776 assert_eq!(erased.unwrap().value, 1);
1777 assert_eq!(list.len(), 1);
1778 assert_eq!(list.front().unwrap().value, 3); let mut cursor = list.cursor_mut();
1782 let erased = cursor.erase(); assert!(erased.is_some());
1784 assert_eq!(erased.unwrap().value, 3);
1785 assert_eq!(list.len(), 0);
1786 assert!(list.is_empty());
1787
1788 list.clear();
1789 }
1790
1791 #[test]
1792 fn test_erase_if() {
1793 stack_pin_init!(let list =
1794 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
1795 let list = unsafe { list.get_unchecked_mut() };
1796
1797 list.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1798 list.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1799 list.push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1800
1801 let erased = list.erase_if(|obj| obj.value % 2 == 0);
1802 assert!(erased.is_some());
1803 assert_eq!(erased.unwrap().value, 2);
1804
1805 assert_eq!(list.len(), 2);
1806 let mut iter = list.iter();
1807 assert_eq!(iter.next().unwrap().value, 1);
1808 assert_eq!(iter.next().unwrap().value, 3);
1809 assert!(iter.next().is_none());
1810
1811 list.clear();
1812 }
1813
1814 #[test]
1815 fn test_erase_by_reference() {
1816 stack_pin_init!(let list =
1817 DoublyLinkedList::<*mut TestObject, DefaultObjectTag, TrackingSize>::new());
1818 let list = unsafe { list.get_unchecked_mut() };
1819 let mut obj1 = TestObject::new(1);
1820 let mut obj2 = TestObject::new(2);
1821 let mut obj3 = TestObject::new(3);
1822
1823 unsafe {
1824 list.push_back_raw(&mut obj1);
1825 list.push_back_raw(&mut obj2);
1826 list.push_back_raw(&mut obj3);
1827 }
1828
1829 assert_eq!(list.len(), 3);
1830
1831 let erased = unsafe { list.erase(&obj2) };
1833 assert!(erased.is_some());
1834 assert_eq!(unsafe { &*erased.unwrap() }.value, 2);
1835 assert_eq!(list.len(), 2);
1836
1837 let mut iter = list.iter();
1838 assert_eq!(iter.next().unwrap().value, 1);
1839 assert_eq!(iter.next().unwrap().value, 3);
1840 assert!(iter.next().is_none());
1841
1842 list.clear();
1843 }
1844
1845 #[test]
1846 fn test_remove_from_container() {
1847 stack_pin_init!(let list = DoublyLinkedList::<*mut TestObject>::new());
1848 let list = unsafe { list.get_unchecked_mut() };
1849 let mut obj1 = TestObject::new(1);
1850 let mut obj2 = TestObject::new(2);
1851 let mut obj3 = TestObject::new(3);
1852
1853 let removed = unsafe {
1855 remove_from_container::<TestObject, DefaultObjectTag, *mut TestObject>(&obj1)
1856 };
1857 assert!(removed.is_none());
1858
1859 unsafe {
1860 list.push_back_raw(&mut obj1);
1861 list.push_back_raw(&mut obj2);
1862 list.push_back_raw(&mut obj3);
1863 }
1864
1865 let removed = unsafe {
1867 remove_from_container::<TestObject, DefaultObjectTag, *mut TestObject>(&obj2)
1868 };
1869 assert!(removed.is_some());
1870 assert_eq!(unsafe { &*removed.unwrap() }.value, 2);
1871
1872 let mut iter = list.iter();
1873 assert_eq!(iter.next().unwrap().value, 1);
1874 assert_eq!(iter.next().unwrap().value, 3);
1875 assert!(iter.next().is_none());
1876
1877 let removed = unsafe {
1879 remove_from_container::<TestObject, DefaultObjectTag, *mut TestObject>(&obj1)
1880 };
1881 assert!(removed.is_some());
1882 assert_eq!(unsafe { &*removed.unwrap() }.value, 1);
1883
1884 let mut iter = list.iter();
1885 assert_eq!(iter.next().unwrap().value, 3);
1886 assert!(iter.next().is_none());
1887
1888 let removed = unsafe {
1890 remove_from_container::<TestObject, DefaultObjectTag, *mut TestObject>(&obj3)
1891 };
1892 assert!(removed.is_some());
1893 assert_eq!(unsafe { &*removed.unwrap() }.value, 3);
1894 assert!(list.is_empty());
1895
1896 list.clear();
1897 }
1898
1899 #[test]
1900 fn test_replace() {
1901 stack_pin_init!(let list =
1902 DoublyLinkedList::<*mut TestObject, DefaultObjectTag, TrackingSize>::new());
1903 let list = unsafe { list.get_unchecked_mut() };
1904 let mut obj1 = TestObject::new(1);
1905 let mut obj2 = TestObject::new(2);
1906 let mut obj3 = TestObject::new(3);
1907
1908 unsafe {
1909 list.push_back_raw(&mut obj1);
1910 list.push_back_raw(&mut obj2);
1911 }
1912
1913 assert_eq!(list.len(), 2);
1914
1915 let old = unsafe { list.replace_raw(&obj2, &mut obj3) };
1916 assert!(old.is_some());
1917 assert_eq!(unsafe { &*old.unwrap() }.value, 2);
1918 assert_eq!(list.len(), 2);
1919
1920 let mut iter = list.iter();
1921 assert_eq!(iter.next().unwrap().value, 1);
1922 assert_eq!(iter.next().unwrap().value, 3);
1923 assert!(iter.next().is_none());
1924
1925 list.clear();
1926 }
1927
1928 #[test]
1929 fn test_cursor_replace() {
1930 stack_pin_init!(let list = DoublyLinkedList::<UniquePtr<UniqueTestObject>>::new());
1931 let list = unsafe { list.get_unchecked_mut() };
1932
1933 let obj1 = UniquePtr::try_new(UniqueTestObject::new(1)).unwrap();
1934 let obj2 = UniquePtr::try_new(UniqueTestObject::new(2)).unwrap();
1935 let obj3 = UniquePtr::try_new(UniqueTestObject::new(3)).unwrap();
1936
1937 list.push_back(obj1);
1938 list.push_back(obj2);
1939
1940 let mut cursor = list.cursor_mut();
1941 cursor.move_next(); let old = cursor.replace(obj3);
1944 assert!(old.is_some());
1945 assert_eq!(old.unwrap().value, 2);
1946
1947 let mut iter = list.iter();
1948 assert_eq!(iter.next().unwrap().value, 1);
1949 assert_eq!(iter.next().unwrap().value, 3);
1950 assert!(iter.next().is_none());
1951
1952 list.clear();
1953 }
1954
1955 struct Tag2;
1956
1957 #[fbl::ref_counted]
1958 #[derive(crate::DoublyLinkedListContainable, crate::Recyclable)]
1959 #[repr(C)]
1960 struct MultiListObject {
1961 value: i32,
1962 #[dll_node]
1963 node1: DoublyLinkedListNode<MultiListObject>,
1964 #[dll_node(tag = Tag2)]
1965 node2: DoublyLinkedListNode<MultiListObject>,
1966 }
1967
1968 #[test]
1969 fn test_multiple_containers() {
1970 stack_pin_init!(let list1 =
1971 DoublyLinkedList::<RefPtr<MultiListObject>, DefaultObjectTag>::new());
1972 let list1 = unsafe { list1.get_unchecked_mut() };
1973 stack_pin_init!(let list2 = DoublyLinkedList::<RefPtr<MultiListObject>, Tag2>::new());
1974 let list2 = unsafe { list2.get_unchecked_mut() };
1975
1976 let obj1 = fbl::make_ref_counted!(MultiListObject {
1977 value: 1,
1978 node1: DoublyLinkedListNode::new(),
1979 node2: DoublyLinkedListNode::new(),
1980 })
1981 .unwrap();
1982
1983 let obj2 = fbl::make_ref_counted!(MultiListObject {
1984 value: 2,
1985 node1: DoublyLinkedListNode::new(),
1986 node2: DoublyLinkedListNode::new(),
1987 })
1988 .unwrap();
1989
1990 list1.push_back(obj1.clone());
1991 list1.push_back(obj2.clone());
1992
1993 list2.push_back(obj2); let mut iter1 = list1.iter();
1996 assert_eq!(iter1.next().unwrap().value, 1);
1997 assert_eq!(iter1.next().unwrap().value, 2);
1998 assert!(iter1.next().is_none());
1999
2000 let mut iter2 = list2.iter();
2001 assert_eq!(iter2.next().unwrap().value, 2);
2002 assert!(iter2.next().is_none());
2003
2004 list1.clear();
2005 list2.clear();
2006 }
2007
2008 use alloc::sync::Arc;
2009 use core::sync::atomic::{AtomicBool, Ordering};
2010
2011 #[derive(crate::DoublyLinkedListContainable, crate::Recyclable)]
2012 struct LifecycleObject {
2013 destroyed: Arc<AtomicBool>,
2014 #[dll_node]
2015 node: DoublyLinkedListNode<LifecycleObject>,
2016 }
2017
2018 impl LifecycleObject {
2019 fn new(destroyed: Arc<AtomicBool>) -> Self {
2020 Self { destroyed, node: DoublyLinkedListNode::new() }
2021 }
2022 }
2023
2024 impl Drop for LifecycleObject {
2025 fn drop(&mut self) {
2026 self.destroyed.store(true, Ordering::Relaxed);
2027 }
2028 }
2029
2030 #[test]
2031 fn test_lifecycle_on_drop() {
2032 let destroyed1 = Arc::new(AtomicBool::new(false));
2033 let destroyed2 = Arc::new(AtomicBool::new(false));
2034
2035 {
2036 stack_pin_init!(let list = DoublyLinkedList::<UniquePtr<LifecycleObject>>::new());
2037 let list = unsafe { list.get_unchecked_mut() };
2038
2039 let obj1 = UniquePtr::try_new(LifecycleObject::new(destroyed1.clone())).unwrap();
2040 let obj2 = UniquePtr::try_new(LifecycleObject::new(destroyed2.clone())).unwrap();
2041
2042 list.push_back(obj1);
2043 list.push_back(obj2);
2044
2045 assert!(!destroyed1.load(Ordering::Relaxed));
2046 assert!(!destroyed2.load(Ordering::Relaxed));
2047 } assert!(destroyed1.load(Ordering::Relaxed));
2050 assert!(destroyed2.load(Ordering::Relaxed));
2051 }
2052
2053 #[test]
2054 fn test_sized_managed_list() {
2055 stack_pin_init!(let list =
2056 DoublyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new());
2057 let list = unsafe { list.get_unchecked_mut() };
2058
2059 assert_eq!(list.len(), 0);
2060
2061 let obj1 = UniquePtr::try_new(UniqueTestObject::new(1)).unwrap();
2062 let obj2 = UniquePtr::try_new(UniqueTestObject::new(2)).unwrap();
2063
2064 list.push_back(obj1);
2065 assert_eq!(list.len(), 1);
2066
2067 list.push_back(obj2);
2068 assert_eq!(list.len(), 2);
2069
2070 let popped = list.pop_front();
2071 assert!(popped.is_some());
2072 assert_eq!(list.len(), 1);
2073
2074 list.clear();
2075 assert_eq!(list.len(), 0);
2076 }
2077
2078 #[test]
2079 fn test_unidirectional_iterators() {
2080 stack_pin_init!(let list = DoublyLinkedList::<UniquePtr<UniqueTestObject>>::new());
2081 let list = unsafe { list.get_unchecked_mut() };
2082
2083 list.push_back(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
2084 list.push_back(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
2085 list.push_back(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
2086
2087 let mut f_iter = list.forward_iter();
2089 assert_eq!(f_iter.next().unwrap().value, 1);
2090 let obj2_ref = f_iter.next().unwrap();
2091 assert_eq!(obj2_ref.value, 2);
2092 assert_eq!(f_iter.next().unwrap().value, 3);
2093 assert!(f_iter.next().is_none());
2094
2095 let mut f_element_iter =
2097 ForwardIterator::<UniquePtr<UniqueTestObject>>::from_element(obj2_ref);
2098 assert_eq!(f_element_iter.next().unwrap().value, 2);
2099 assert_eq!(f_element_iter.next().unwrap().value, 3);
2100 assert!(f_element_iter.next().is_none());
2101
2102 let mut r_iter = list.reverse_iter();
2104 assert_eq!(r_iter.next().unwrap().value, 3);
2105 let obj2_ref_r = r_iter.next().unwrap();
2106 assert_eq!(obj2_ref_r.value, 2);
2107 assert_eq!(r_iter.next().unwrap().value, 1);
2108 assert!(r_iter.next().is_none());
2109
2110 let mut r_element_iter =
2112 ReverseIterator::<UniquePtr<UniqueTestObject>>::from_element(obj2_ref_r);
2113 assert_eq!(r_element_iter.next().unwrap().value, 2);
2114 assert_eq!(r_element_iter.next().unwrap().value, 1);
2115 assert!(r_element_iter.next().is_none());
2116
2117 list.clear();
2118 }
2119
2120 #[test]
2121 fn test_cursor_at() {
2122 stack_pin_init!(let list =
2123 DoublyLinkedList::<*mut TestObject, DefaultObjectTag, TrackingSize>::new());
2124 let list = unsafe { list.get_unchecked_mut() };
2125 let mut obj1 = TestObject::new(1);
2126 let mut obj2 = TestObject::new(2);
2127 let mut obj3 = TestObject::new(3);
2128
2129 unsafe {
2130 list.push_back_raw(&mut obj1);
2131 list.push_back_raw(&mut obj2);
2132 list.push_back_raw(&mut obj3);
2133 }
2134
2135 let mut cursor = unsafe { list.cursor_at(&obj2) };
2138 assert_eq!(cursor.get().unwrap().value, 2);
2139
2140 cursor.move_next();
2142 assert_eq!(cursor.get().unwrap().value, 3);
2143
2144 let mut cursor = unsafe { list.cursor_at(&obj2) };
2147 cursor.move_prev();
2148 assert_eq!(cursor.get().unwrap().value, 1);
2149
2150 let mut cursor = unsafe { list.cursor_at(&obj2) };
2153 let erased = cursor.erase().unwrap();
2154 assert_eq!(unsafe { &*erased }.value, 2);
2155
2156 let mut iter = list.iter();
2158 assert_eq!(iter.next().unwrap().value, 1);
2159 assert_eq!(iter.next().unwrap().value, 3);
2160 assert!(iter.next().is_none());
2161
2162 list.clear();
2163 }
2164
2165 unsafe extern "C" {
2167 fn cpp_create_unique_list() -> *mut c_void;
2169 fn cpp_destroy_unique_list(list: *mut c_void);
2170 fn cpp_unique_list_push_back(list: *mut c_void, item: *mut c_void);
2171 fn cpp_unique_list_pop_front(list: *mut c_void) -> *mut c_void;
2172 fn cpp_unique_list_is_empty(list: *mut c_void) -> bool;
2173
2174 fn cpp_create_ref_list() -> *mut c_void;
2176 fn cpp_destroy_ref_list(list: *mut c_void);
2177 fn cpp_ref_list_push_back(list: *mut c_void, item: *mut c_void);
2178 fn cpp_ref_list_pop_front(list: *mut c_void) -> *mut c_void;
2179 fn cpp_ref_list_is_empty(list: *mut c_void) -> bool;
2180
2181 fn cpp_create_unique_object(value: i32, destruction_flag: *mut bool) -> *mut c_void;
2183 fn cpp_get_unique_object_value(obj: *mut c_void) -> i32;
2184
2185 fn cpp_create_ref_object(value: i32, destruction_flag: *mut bool) -> *mut c_void;
2187 fn cpp_get_ref_object_value(obj: *mut c_void) -> i32;
2188 }
2189
2190 #[test]
2191 fn test_interop_rust_list_cpp_unique_objects() {
2192 let destroyed1 = AtomicBool::new(false);
2193 let destroyed2 = AtomicBool::new(false);
2194
2195 unsafe {
2196 stack_pin_init!(let list = DoublyLinkedList::<UniquePtr<SharedUniqueObject>>::new());
2197 let list = list.get_unchecked_mut();
2198
2199 let cpp_raw1 = cpp_create_unique_object(1, destroyed1.as_ptr() as *mut bool);
2200 let cpp_raw2 = cpp_create_unique_object(2, destroyed2.as_ptr() as *mut bool);
2201
2202 let obj1 = UniquePtr::from_raw(cpp_raw1 as *mut SharedUniqueObject);
2203 let obj2 = UniquePtr::from_raw(cpp_raw2 as *mut SharedUniqueObject);
2204
2205 list.push_back(obj1);
2206 list.push_back(obj2);
2207
2208 assert!(!destroyed1.load(Ordering::Relaxed));
2209 assert!(!destroyed2.load(Ordering::Relaxed));
2210
2211 let popped = list.pop_front();
2213 assert!(popped.is_some());
2214 assert_eq!(popped.as_ref().unwrap().value, 1);
2215
2216 drop(popped);
2218 assert!(destroyed1.load(Ordering::Relaxed));
2219 assert!(!destroyed2.load(Ordering::Relaxed));
2220
2221 }
2223 assert!(destroyed2.load(Ordering::Relaxed));
2224 }
2225
2226 #[test]
2227 fn test_interop_cpp_list_rust_unique_objects() {
2228 let destroyed1 = Arc::new(AtomicBool::new(false));
2229 let destroyed2 = Arc::new(AtomicBool::new(false));
2230
2231 unsafe {
2232 let cpp_list = cpp_create_unique_list();
2233 assert!(cpp_unique_list_is_empty(cpp_list));
2234
2235 let obj1 = UniquePtr::try_new(SharedUniqueObject::new(1)).unwrap();
2236 let obj2 = UniquePtr::try_new(SharedUniqueObject::new(2)).unwrap();
2237
2238 let raw1 = UniquePtr::as_ptr(&obj1) as *mut SharedUniqueObject;
2240 (*raw1).destruction_flag = destroyed1.as_ptr() as *mut bool;
2241 let raw2 = UniquePtr::as_ptr(&obj2) as *mut SharedUniqueObject;
2242 (*raw2).destruction_flag = destroyed2.as_ptr() as *mut bool;
2243
2244 cpp_unique_list_push_back(cpp_list, UniquePtr::into_raw(obj1) as *mut c_void);
2246 cpp_unique_list_push_back(cpp_list, UniquePtr::into_raw(obj2) as *mut c_void);
2247
2248 assert!(!destroyed1.load(Ordering::Relaxed));
2249 assert!(!destroyed2.load(Ordering::Relaxed));
2250
2251 let popped = cpp_unique_list_pop_front(cpp_list);
2253 assert!(!popped.is_null());
2254 assert_eq!(cpp_get_unique_object_value(popped), 1);
2255
2256 let popped_rust = UniquePtr::from_raw(popped as *mut SharedUniqueObject);
2258 drop(popped_rust);
2259 assert!(destroyed1.load(Ordering::Relaxed));
2260 assert!(!destroyed2.load(Ordering::Relaxed));
2261
2262 cpp_destroy_unique_list(cpp_list);
2264 }
2265 assert!(destroyed2.load(Ordering::Relaxed));
2266 }
2267
2268 #[test]
2269 fn test_interop_rust_list_cpp_ref_objects() {
2270 let destroyed1 = AtomicBool::new(false);
2271 let destroyed2 = AtomicBool::new(false);
2272
2273 unsafe {
2274 stack_pin_init!(let list = DoublyLinkedList::<RefPtr<SharedRefObject>>::new());
2275 let list = list.get_unchecked_mut();
2276
2277 let cpp_raw1 = cpp_create_ref_object(1, destroyed1.as_ptr() as *mut bool);
2278 let cpp_raw2 = cpp_create_ref_object(2, destroyed2.as_ptr() as *mut bool);
2279
2280 let obj1 = RefPtr::from_raw(cpp_raw1 as *mut SharedRefObject);
2281 let obj2 = RefPtr::from_raw(cpp_raw2 as *mut SharedRefObject);
2282
2283 list.push_back(obj1);
2284 list.push_back(obj2);
2285
2286 assert!(!destroyed1.load(Ordering::Relaxed));
2287 assert!(!destroyed2.load(Ordering::Relaxed));
2288
2289 let popped = list.pop_front();
2291 assert!(popped.is_some());
2292 assert_eq!(popped.as_ref().unwrap().value, 1);
2293
2294 drop(popped);
2296 assert!(destroyed1.load(Ordering::Relaxed));
2297 assert!(!destroyed2.load(Ordering::Relaxed));
2298
2299 }
2301 assert!(destroyed2.load(Ordering::Relaxed));
2302 }
2303
2304 #[test]
2305 fn test_interop_cpp_list_rust_ref_objects() {
2306 let destroyed1 = Arc::new(AtomicBool::new(false));
2307 let destroyed2 = Arc::new(AtomicBool::new(false));
2308
2309 unsafe {
2310 let cpp_list = cpp_create_ref_list();
2311 assert!(cpp_ref_list_is_empty(cpp_list));
2312
2313 let obj1 = SharedRefObject::new_ref_counted(1);
2314 let obj2 = SharedRefObject::new_ref_counted(2);
2315
2316 let raw1 = RefPtr::as_ptr(&obj1) as *mut SharedRefObject;
2318 (*raw1).destruction_flag = destroyed1.as_ptr() as *mut bool;
2319 let raw2 = RefPtr::as_ptr(&obj2) as *mut SharedRefObject;
2320 (*raw2).destruction_flag = destroyed2.as_ptr() as *mut bool;
2321
2322 cpp_ref_list_push_back(
2324 cpp_list,
2325 RefPtr::into_raw(obj1) as *mut SharedRefObject as *mut c_void,
2326 );
2327 cpp_ref_list_push_back(
2328 cpp_list,
2329 RefPtr::into_raw(obj2) as *mut SharedRefObject as *mut c_void,
2330 );
2331
2332 assert!(!destroyed1.load(Ordering::Relaxed));
2333 assert!(!destroyed2.load(Ordering::Relaxed));
2334
2335 let popped = cpp_ref_list_pop_front(cpp_list);
2337 assert!(!popped.is_null());
2338 assert_eq!(cpp_get_ref_object_value(popped), 1);
2339
2340 let popped_rust = RefPtr::from_raw(popped as *mut SharedRefObject);
2342 drop(popped_rust);
2343 assert!(destroyed1.load(Ordering::Relaxed));
2344 assert!(!destroyed2.load(Ordering::Relaxed));
2345
2346 cpp_destroy_ref_list(cpp_list);
2348 }
2349 assert!(destroyed2.load(Ordering::Relaxed));
2350 }
2351}