1use crate::ptr_traits::{ManagedPtr, PtrTraits};
6use crate::size_tracker::{NonTrackingSize, SizeTracker, TrackingSize};
7use crate::tag::DefaultObjectTag;
8use core::cell::UnsafeCell;
9
10#[repr(C)]
12pub struct SinglyLinkedListNode<T> {
13 pub next: UnsafeCell<*mut T>,
17}
18
19impl<T> SinglyLinkedListNode<T> {
20 pub const fn new() -> Self {
22 Self { next: UnsafeCell::new(core::ptr::null_mut()) }
23 }
24
25 pub fn in_container(&self) -> bool {
27 !unsafe { *self.next.get() }.is_null()
30 }
31
32 fn get_next(&self) -> *mut T {
33 unsafe { *self.next.get() }
35 }
36
37 fn set_next(&self, next: *mut T) {
38 unsafe {
41 *self.next.get() = next;
42 }
43 }
44}
45
46impl<T> core::fmt::Debug for SinglyLinkedListNode<T> {
47 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
48 f.debug_struct("SinglyLinkedListNode").field("in_container", &self.in_container()).finish()
49 }
50}
51
52impl<T> Default for SinglyLinkedListNode<T> {
53 fn default() -> Self {
54 Self::new()
55 }
56}
57
58impl<T> Drop for SinglyLinkedListNode<T> {
59 fn drop(&mut self) {
60 debug_assert!(!self.in_container(), "Object destroyed while still in container");
61 }
62}
63
64pub trait SinglyLinkedListContainable<T, Tag = DefaultObjectTag> {
71 fn get_node(&self) -> &SinglyLinkedListNode<T>;
73}
74
75#[repr(C)]
213pub struct SinglyLinkedList<P, Tag = DefaultObjectTag, S = NonTrackingSize>
214where
215 P: PtrTraits,
216 P::Target: SinglyLinkedListContainable<P::Target, Tag>,
217 S: SizeTracker,
218{
219 head: *mut P::Target,
220 size: S,
221 _phantom: core::marker::PhantomData<(P, Tag)>,
222}
223
224impl<P, Tag, S> SinglyLinkedList<P, Tag, S>
225where
226 P: PtrTraits,
227 P::Target: SinglyLinkedListContainable<P::Target, Tag>,
228 S: SizeTracker,
229{
230 pub const fn new() -> Self {
232 Self {
233 head: crate::make_sentinel_null(),
234 size: S::INIT,
235 _phantom: core::marker::PhantomData,
236 }
237 }
238
239 unsafe fn get_node_ref<'a>(&self, ptr: *mut P::Target) -> &'a SinglyLinkedListNode<P::Target> {
244 let _ = self;
245 unsafe { &(*ptr) }.get_node()
247 }
248
249 pub fn is_empty(&self) -> bool {
251 crate::is_sentinel_ptr(self.head)
252 }
253
254 pub fn front(&self) -> Option<&P::Target> {
256 if self.is_empty() {
257 None
258 } else {
259 unsafe { Some(&*self.head) }
261 }
262 }
263
264 pub fn front_mut(&mut self) -> Option<&mut P::Target> {
266 if self.is_empty() {
267 None
268 } else {
269 unsafe { Some(&mut *self.head) }
272 }
273 }
274
275 pub fn push_front(&mut self, ptr: P)
281 where
282 P: ManagedPtr,
283 {
284 unsafe { self.push_front_raw(ptr) }
287 }
288
289 pub unsafe fn push_front_raw(&mut self, ptr: P) {
302 let raw = P::into_raw(ptr);
303 debug_assert!(!raw.is_null());
304 let node = unsafe { self.get_node_ref(raw) };
306 assert!(!node.in_container());
307
308 node.set_next(self.head);
309 self.head = raw;
310 self.size.increment();
311 }
312
313 pub fn pop_front(&mut self) -> Option<P> {
315 if self.is_empty() {
316 return None;
317 }
318
319 let ptr = self.head;
320 self.size.decrement();
321
322 let node = unsafe { self.get_node_ref(ptr) };
324
325 self.head = node.get_next();
326 node.set_next(core::ptr::null_mut());
327
328 Some(unsafe { P::from_raw(ptr) })
330 }
331
332 pub fn clear(&mut self) {
334 while let Some(_) = self.pop_front() {}
335 }
336
337 pub unsafe fn insert_after_raw(&mut self, pos: *mut P::Target, ptr: P) {
346 debug_assert!(!pos.is_null());
347 let raw = P::into_raw(ptr);
348 debug_assert!(!raw.is_null());
349 let node = unsafe { self.get_node_ref(raw) };
351 debug_assert!(!node.in_container());
352
353 let pos_node = unsafe { self.get_node_ref(pos) };
355 node.set_next(pos_node.get_next());
356 pos_node.set_next(raw);
357 self.size.increment();
358 }
359
360 pub unsafe fn erase_next_raw(&mut self, pos: *mut P::Target) -> Option<P> {
368 debug_assert!(!pos.is_null());
369 let pos_node = unsafe { self.get_node_ref(pos) };
371 let next_ptr = pos_node.get_next();
372 if crate::is_sentinel_ptr(next_ptr) {
373 return None;
374 }
375 let next_node = unsafe { self.get_node_ref(next_ptr) };
377 pos_node.set_next(next_node.get_next());
378 next_node.set_next(core::ptr::null_mut());
379 self.size.decrement();
380 Some(unsafe { P::from_raw(next_ptr) })
382 }
383
384 pub fn swap(&mut self, other: &mut Self) {
386 core::mem::swap(&mut self.head, &mut other.head);
387 self.size.swap(&mut other.size);
388 }
389
390 pub fn erase_if<F>(&mut self, mut f: F) -> Option<P>
393 where
394 F: FnMut(&P::Target) -> bool,
395 {
396 if let Some(head_ref) = self.front() {
398 if f(head_ref) {
399 return self.pop_front();
400 }
401 }
402
403 if self.is_empty() {
404 return None;
405 }
406
407 let mut cursor = self.cursor_mut();
409 while let Some(next_ref) = cursor.get_next() {
410 if f(next_ref) {
411 return cursor.erase_next();
412 }
413 cursor.move_next();
414 }
415
416 None
417 }
418
419 pub fn replace_if<F>(&mut self, f: F, value: P) -> Option<P>
426 where
427 F: FnMut(&P::Target) -> bool,
428 P: ManagedPtr,
429 {
430 unsafe { self.replace_if_raw(f, value) }
431 }
432
433 pub unsafe fn replace_if_raw<F>(&mut self, mut f: F, value: P) -> Option<P>
445 where
446 F: FnMut(&P::Target) -> bool,
447 {
448 if let Some(head_ref) = self.front() {
450 if f(head_ref) {
451 let old_head = self.pop_front().unwrap();
452 unsafe { self.push_front_raw(value) };
455 return Some(old_head);
456 }
457 }
458
459 let mut cursor = self.cursor_mut();
461 while let Some(next_ref) = cursor.get_next() {
462 if f(next_ref) {
463 unsafe {
466 return cursor.replace_next_raw(value);
467 }
468 }
469 cursor.move_next();
470 }
471
472 None
473 }
474
475 pub unsafe fn split_after_raw(&mut self, pos: *mut P::Target) -> Self {
482 debug_assert!(!pos.is_null());
483 let pos_node = unsafe { &(*pos) }.get_node();
485 let next_ptr = unsafe { *pos_node.next.get() };
486
487 unsafe { *pos_node.next.get() = crate::make_sentinel_null() };
488
489 let mut new_list =
490 Self { head: next_ptr, size: S::INIT, _phantom: core::marker::PhantomData };
491
492 if S::IS_TRACKING {
493 let new_size = new_list.size_slow();
494 new_list.size.set(new_size);
495 self.size.set(self.size.get() - new_size);
496 }
497
498 new_list
499 }
500
501 pub fn retain<F>(&mut self, mut f: F)
503 where
504 F: FnMut(&P::Target) -> bool,
505 {
506 self.erase_if(|x| !f(x));
507 }
508
509 pub fn cursor_mut(&mut self) -> CursorMut<'_, P, Tag, S> {
511 let head = self.head;
512 CursorMut { list: self, current: head }
513 }
514
515 pub fn size_slow(&self) -> usize {
517 if let Some(head) = self.front() {
518 let iter = Iterator::<'_, P, Tag>::from_element(head);
519 let mut count = 0;
520 for _ in iter {
521 count += 1;
522 }
523 count
524 } else {
525 0
526 }
527 }
528
529 pub fn find_if<F>(&self, mut f: F) -> Option<&P::Target>
531 where
532 F: FnMut(&P::Target) -> bool,
533 {
534 self.iter().find(|&x| f(x))
535 }
536
537 pub fn iter(&self) -> Iterator<'_, P, Tag> {
539 Iterator::new(self.head)
540 }
541}
542
543impl<P, Tag> SinglyLinkedList<P, Tag, TrackingSize>
544where
545 P: PtrTraits,
546 P::Target: SinglyLinkedListContainable<P::Target, Tag>,
547{
548 pub fn size(&self) -> usize {
550 self.size.get()
551 }
552}
553
554impl<P, Tag, S> Drop for SinglyLinkedList<P, Tag, S>
555where
556 P: PtrTraits,
557 P::Target: SinglyLinkedListContainable<P::Target, Tag>,
558 S: SizeTracker,
559{
560 fn drop(&mut self) {
561 if P::IS_MANAGED {
562 self.clear();
563 } else {
564 debug_assert!(self.is_empty(), "List must be empty on destruction");
565 if S::IS_TRACKING {
566 debug_assert_eq!(self.size.get(), 0, "Size must be zero on destruction");
567 }
568 }
569 }
570}
571
572pub struct Iterator<'a, P, Tag = DefaultObjectTag>
574where
575 P: PtrTraits,
576 P::Target: SinglyLinkedListContainable<P::Target, Tag>,
577{
578 current: *mut P::Target,
579 _phantom: core::marker::PhantomData<&'a (P, Tag)>,
580}
581
582impl<'a, P, Tag> Iterator<'a, P, Tag>
583where
584 P: PtrTraits,
585 P::Target: SinglyLinkedListContainable<P::Target, Tag>,
586{
587 fn new(current: *mut P::Target) -> Self {
588 Self { current, _phantom: core::marker::PhantomData }
589 }
590}
591
592impl<'a, P, Tag> core::iter::Iterator for Iterator<'a, P, Tag>
593where
594 P: PtrTraits,
595 P::Target: SinglyLinkedListContainable<P::Target, Tag>,
596{
597 type Item = &'a P::Target;
598
599 fn next(&mut self) -> Option<Self::Item> {
600 if crate::is_sentinel_ptr(self.current) {
601 None
602 } else {
603 let current = unsafe { &*self.current };
606 self.current = unsafe { *current.get_node().next.get() };
608 Some(current)
609 }
610 }
611}
612
613impl<'a, P, Tag> Iterator<'a, P, Tag>
614where
615 P: PtrTraits,
616 P::Target: SinglyLinkedListContainable<P::Target, Tag>,
617{
618 pub fn from_element(obj: &'a P::Target) -> Self {
624 assert!(obj.get_node().in_container(), "Object must be in a container");
625 Self { current: obj as *const _ as *mut _, _phantom: core::marker::PhantomData }
626 }
627}
628
629pub struct CursorMut<'a, P, Tag = DefaultObjectTag, S = NonTrackingSize>
631where
632 P: PtrTraits,
633 P::Target: SinglyLinkedListContainable<P::Target, Tag>,
634 S: SizeTracker,
635{
636 list: &'a mut SinglyLinkedList<P, Tag, S>,
637 current: *mut P::Target,
638}
639
640impl<'a, P, Tag, S> CursorMut<'a, P, Tag, S>
641where
642 P: PtrTraits,
643 P::Target: SinglyLinkedListContainable<P::Target, Tag>,
644 S: SizeTracker,
645{
646 pub fn get(&self) -> Option<&P::Target> {
648 if crate::is_sentinel_ptr(self.current) {
649 None
650 } else {
651 Some(unsafe { &*self.current })
653 }
654 }
655
656 pub fn move_next(&mut self) -> bool {
658 if crate::is_sentinel_ptr(self.current) {
659 return false;
660 }
661 let node = unsafe { self.list.get_node_ref(self.current) };
663 self.current = node.get_next();
664 !crate::is_sentinel_ptr(self.current)
665 }
666
667 pub fn get_next(&self) -> Option<&P::Target> {
669 if crate::is_sentinel_ptr(self.current) {
670 return None;
671 }
672 let node = unsafe { self.list.get_node_ref(self.current) };
674 let next_ptr = node.get_next();
675 if crate::is_sentinel_ptr(next_ptr) {
676 None
677 } else {
678 unsafe { Some(&*next_ptr) }
680 }
681 }
682
683 pub fn insert_after(&mut self, ptr: P)
685 where
686 P: ManagedPtr,
687 {
688 assert!(!crate::is_sentinel_ptr(self.current), "Cannot insert after end sentinel");
689 unsafe { self.list.insert_after_raw(self.current, ptr) }
691 }
692
693 pub fn erase_next(&mut self) -> Option<P> {
695 assert!(!crate::is_sentinel_ptr(self.current), "Cannot erase next of end sentinel");
696 unsafe { self.list.erase_next_raw(self.current) }
698 }
699
700 pub unsafe fn replace_next_raw(&mut self, value: P) -> Option<P> {
711 debug_assert!(!crate::is_sentinel_ptr(self.current), "Cannot replace next of end sentinel");
712
713 let current_node = unsafe { self.list.get_node_ref(self.current) };
715 let next_ptr = current_node.get_next();
716 if crate::is_sentinel_ptr(next_ptr) {
717 return None;
718 }
719
720 let value_raw = P::into_raw(value);
721 let value_node = unsafe { self.list.get_node_ref(value_raw) };
723 assert!(!value_node.in_container());
724
725 let next_node = unsafe { self.list.get_node_ref(next_ptr) };
727
728 value_node.set_next(next_node.get_next());
729 current_node.set_next(value_raw);
730 next_node.set_next(core::ptr::null_mut());
731
732 Some(unsafe { P::from_raw(next_ptr) })
734 }
735}
736
737impl<P, Tag, S> core::fmt::Debug for SinglyLinkedList<P, Tag, S>
738where
739 P: PtrTraits,
740 P::Target: SinglyLinkedListContainable<P::Target, Tag> + core::fmt::Debug,
741 S: SizeTracker,
742{
743 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
744 f.debug_list().entries(self.iter()).finish()
745 }
746}
747
748#[cfg(test)]
749mod tests {
750 extern crate alloc;
751 use super::*;
752 use crate::intrusive_container_test_support::*;
753 use crate::ref_ptr::RefPtr;
754 use crate::unique_ptr::UniquePtr;
755 use alloc::sync::Arc;
756 use core::ffi::c_void;
757 use core::sync::atomic::{AtomicBool, Ordering};
758
759 struct DummyTarget;
761 impl SinglyLinkedListContainable<DummyTarget, DefaultObjectTag> for DummyTarget {
762 fn get_node(&self) -> &SinglyLinkedListNode<DummyTarget> {
763 unreachable!()
764 }
765 }
766
767 zr::static_assert!(
768 core::mem::size_of::<SinglyLinkedList<*mut DummyTarget>>()
769 == core::mem::size_of::<*mut DummyTarget>()
770 );
771 zr::static_assert!(
772 core::mem::align_of::<SinglyLinkedList<*mut DummyTarget>>()
773 == core::mem::align_of::<*mut DummyTarget>()
774 );
775
776 zr::static_assert!(
777 core::mem::size_of::<SinglyLinkedList<*mut DummyTarget, DefaultObjectTag, TrackingSize>>()
778 == 2 * core::mem::size_of::<*mut DummyTarget>()
779 );
780 zr::static_assert!(
781 core::mem::align_of::<SinglyLinkedList<*mut DummyTarget, DefaultObjectTag, TrackingSize>>()
782 == core::mem::align_of::<*mut DummyTarget>()
783 );
784
785 zr::static_assert!(
786 core::mem::size_of::<Iterator<'_, *mut DummyTarget>>()
787 == core::mem::size_of::<*mut DummyTarget>()
788 );
789 zr::static_assert!(
790 core::mem::align_of::<Iterator<'_, *mut DummyTarget>>()
791 == core::mem::align_of::<*mut DummyTarget>()
792 );
793
794 macro_rules! generate_list_tests {
795 ($mod_name:ident, $ptr_type:ty, $factory_type:ty, $get_val:expr, $push:expr) => {
796 mod $mod_name {
797 use super::*;
798
799 #[test]
800 fn test_basic_ops() {
801 let mut factory = <$factory_type>::new();
802 let mut list = SinglyLinkedList::<$ptr_type>::new();
803 assert!(list.is_empty());
804
805 let obj1 = factory.create(1);
806 let obj2 = factory.create(2);
807 let obj3 = factory.create(3);
808
809 $push(&mut list, obj1);
810 $push(&mut list, obj2);
811 $push(&mut list, obj3);
812
813 assert!(!list.is_empty());
814
815 let mut iter = list.iter();
816 assert_eq!(iter.next().unwrap().value, 3);
817 assert_eq!(iter.next().unwrap().value, 2);
818 assert_eq!(iter.next().unwrap().value, 1);
819 assert!(iter.next().is_none());
820
821 assert_eq!($get_val(list.pop_front().unwrap().get_ref()), 3);
822 assert_eq!($get_val(list.pop_front().unwrap().get_ref()), 2);
823 assert_eq!($get_val(list.pop_front().unwrap().get_ref()), 1);
824
825 assert!(list.is_empty());
826 }
827
828 #[test]
829 fn test_insert_after() {
830 let mut factory = <$factory_type>::new();
831 let mut list = SinglyLinkedList::<$ptr_type>::new();
832
833 let obj1 = factory.create(1);
834 let raw1 = <$ptr_type as PtrTraits>::into_raw(obj1);
835 $push(&mut list, unsafe { <$ptr_type as PtrTraits>::from_raw(raw1) });
836
837 let obj2 = factory.create(2);
838 let raw2 = <$ptr_type as PtrTraits>::into_raw(obj2);
839 unsafe {
840 list.insert_after_raw(raw1, <$ptr_type as PtrTraits>::from_raw(raw2));
841 }
842
843 let obj3 = factory.create(3);
844 unsafe {
845 list.insert_after_raw(raw2, obj3);
846 }
847
848 let mut iter = list.iter();
849 assert_eq!(iter.next().unwrap().value, 1);
850 assert_eq!(iter.next().unwrap().value, 2);
851 assert_eq!(iter.next().unwrap().value, 3);
852 assert!(iter.next().is_none());
853
854 list.clear();
856 }
857
858 #[test]
859 fn test_clear() {
860 let mut factory = <$factory_type>::new();
861 let mut list = SinglyLinkedList::<$ptr_type>::new();
862 let obj1 = factory.create(1);
863 let obj2 = factory.create(2);
864
865 $push(&mut list, obj1);
866 $push(&mut list, obj2);
867
868 assert!(!list.is_empty());
869 list.clear();
870 assert!(list.is_empty());
871 }
872
873 #[test]
874 fn test_erase_next() {
875 let mut factory = <$factory_type>::new();
876 let mut list = SinglyLinkedList::<$ptr_type>::new();
877
878 let obj1 = factory.create(1);
879 let raw1 = <$ptr_type as PtrTraits>::into_raw(obj1);
880 $push(&mut list, unsafe { <$ptr_type as PtrTraits>::from_raw(raw1) });
881
882 let obj2 = factory.create(2);
883 let raw2 = <$ptr_type as PtrTraits>::into_raw(obj2);
884 unsafe {
885 list.insert_after_raw(raw1, <$ptr_type as PtrTraits>::from_raw(raw2));
886 }
887
888 let obj3 = factory.create(3);
889 unsafe {
890 list.insert_after_raw(raw2, obj3);
891 }
892
893 let erased = unsafe { list.erase_next_raw(raw1) };
894 assert_eq!($get_val(erased.unwrap().get_ref()), 2);
895
896 let mut iter = list.iter();
897 assert_eq!(iter.next().unwrap().value, 1);
898 assert_eq!(iter.next().unwrap().value, 3);
899 assert!(iter.next().is_none());
900
901 list.clear();
903 }
904
905 #[test]
906 fn test_swap() {
907 let mut factory = <$factory_type>::new();
908 let mut list1 = SinglyLinkedList::<$ptr_type>::new();
909 let mut list2 = SinglyLinkedList::<$ptr_type>::new();
910
911 let obj1 = factory.create(1);
912 let obj2 = factory.create(2);
913
914 $push(&mut list1, obj1);
915 $push(&mut list2, obj2);
916
917 list1.swap(&mut list2);
918
919 assert_eq!($get_val(list1.pop_front().unwrap().get_ref()), 2);
920 assert_eq!($get_val(list2.pop_front().unwrap().get_ref()), 1);
921 }
922
923 #[test]
924 fn test_size_slow() {
925 let mut factory = <$factory_type>::new();
926 let mut list = SinglyLinkedList::<$ptr_type>::new();
927 let obj1 = factory.create(1);
928 let obj2 = factory.create(2);
929
930 assert_eq!(list.size_slow(), 0);
931
932 $push(&mut list, obj1);
933 assert_eq!(list.size_slow(), 1);
934 $push(&mut list, obj2);
935 assert_eq!(list.size_slow(), 2);
936
937 list.pop_front();
938 assert_eq!(list.size_slow(), 1);
939
940 list.pop_front();
941 assert_eq!(list.size_slow(), 0);
942 }
943
944 #[test]
945 fn test_find_if() {
946 let mut factory = <$factory_type>::new();
947 let mut list = SinglyLinkedList::<$ptr_type>::new();
948 let obj1 = factory.create(1);
949 let obj2 = factory.create(2);
950
951 $push(&mut list, obj1);
952 $push(&mut list, obj2);
953
954 let found = list.find_if(|o| o.value == 1);
955 assert!(found.is_some());
956 assert_eq!(found.unwrap().value, 1);
957
958 let found = list.find_if(|o| o.value == 3);
959 assert!(found.is_none());
960
961 list.clear();
963 }
964
965 #[test]
966 fn test_erase_if() {
967 let mut factory = <$factory_type>::new();
968 let mut list = SinglyLinkedList::<$ptr_type>::new();
969 let obj1 = factory.create(1);
970 let obj2 = factory.create(2);
971 let obj3 = factory.create(3);
972
973 $push(&mut list, obj1);
974 $push(&mut list, obj2);
975 $push(&mut list, obj3);
976
977 let erased = list.erase_if(|o| o.value == 2);
980 assert!(erased.is_some());
981 assert_eq!($get_val(erased.unwrap().get_ref()), 2);
982
983 let mut iter = list.iter();
984 assert_eq!(iter.next().unwrap().value, 3);
985 assert_eq!(iter.next().unwrap().value, 1);
986 assert!(iter.next().is_none());
987
988 list.clear();
990 }
991
992 #[test]
993 fn test_replace_if() {
994 let mut factory = <$factory_type>::new();
995 let mut list = SinglyLinkedList::<$ptr_type>::new();
996 let obj1 = factory.create(1);
997 let obj2 = factory.create(2);
998 let obj3 = factory.create(3);
999
1000 $push(&mut list, obj1);
1001 $push(&mut list, obj2);
1002
1003 let replaced = unsafe { list.replace_if_raw(|o| o.value == 2, obj3) };
1006 assert_eq!($get_val(replaced.unwrap().get_ref()), 2);
1007
1008 let mut iter = list.iter();
1009 assert_eq!(iter.next().unwrap().value, 3);
1010 assert_eq!(iter.next().unwrap().value, 1);
1011 assert!(iter.next().is_none());
1012
1013 list.clear();
1015 }
1016
1017 #[test]
1018 fn test_split_after() {
1019 let mut factory = <$factory_type>::new();
1020 let mut list = SinglyLinkedList::<$ptr_type>::new();
1021 let obj1 = factory.create(1);
1022 let obj2 = factory.create(2);
1023 let obj3 = factory.create(3);
1024
1025 $push(&mut list, obj1);
1026 $push(&mut list, obj2);
1027 $push(&mut list, obj3);
1028
1029 let raw_pos = {
1032 let found = list.find_if(|o| o.value == 2).unwrap();
1033 found as *const <$ptr_type as PtrTraits>::Target
1034 as *mut <$ptr_type as PtrTraits>::Target
1035 };
1036
1037 let mut other = unsafe { list.split_after_raw(raw_pos) };
1038
1039 assert_eq!(list.size_slow(), 2);
1043 assert_eq!(other.size_slow(), 1);
1044
1045 let mut iter = list.iter();
1046 assert_eq!(iter.next().unwrap().value, 3);
1047 assert_eq!(iter.next().unwrap().value, 2);
1048 assert!(iter.next().is_none());
1049
1050 let mut iter = other.iter();
1051 assert_eq!(iter.next().unwrap().value, 1);
1052 assert!(iter.next().is_none());
1053
1054 list.clear();
1056 other.clear();
1057 }
1058 }
1059 };
1060 }
1061
1062 #[derive(fbl::Recyclable, crate::SinglyLinkedListContainable)]
1063 struct TestObject {
1064 value: i32,
1065 #[sll_node]
1066 node: SinglyLinkedListNode<TestObject>,
1067 }
1068
1069 impl TestObject {
1070 fn new(value: i32) -> Self {
1071 Self { value, node: SinglyLinkedListNode::new() }
1072 }
1073 }
1074
1075 impl TestValue for TestObject {
1076 fn new(value: i32) -> Self {
1077 Self::new(value)
1078 }
1079 }
1080
1081 generate_list_tests!(
1082 raw_ptr_tests,
1083 *mut TestObject,
1084 RawFactory<TestObject>,
1085 |p: &TestObject| p.value,
1086 |list: &mut SinglyLinkedList<*mut TestObject>, obj| unsafe {
1087 list.push_front_raw(obj);
1088 }
1089 );
1090
1091 #[derive(fbl::Recyclable, crate::SinglyLinkedListContainable)]
1092 struct UniqueTestObject {
1093 value: i32,
1094 #[sll_node]
1095 node: SinglyLinkedListNode<UniqueTestObject>,
1096 }
1097
1098 impl UniqueTestObject {
1099 fn new(value: i32) -> Self {
1100 Self { value, node: SinglyLinkedListNode::new() }
1101 }
1102 }
1103
1104 impl TestValue for UniqueTestObject {
1105 fn new(value: i32) -> Self {
1106 Self::new(value)
1107 }
1108 }
1109
1110 generate_list_tests!(
1111 unique_ptr_tests,
1112 UniquePtr<UniqueTestObject>,
1113 UniqueFactory<UniqueTestObject>,
1114 |p: &UniqueTestObject| p.value,
1115 |list: &mut SinglyLinkedList<UniquePtr<UniqueTestObject>>, obj| list.push_front(obj)
1116 );
1117
1118 #[fbl::ref_counted]
1119 #[derive(crate::SinglyLinkedListContainable, crate::Recyclable)]
1120 #[repr(C)]
1121 pub struct RefTestObject {
1122 value: i32,
1123 #[sll_node]
1124 node: SinglyLinkedListNode<RefTestObject>,
1125 }
1126
1127 impl TestValue for RefTestObject {
1128 fn new_ref_counted(value: i32) -> RefPtr<Self> {
1129 crate::make_ref_counted!(RefTestObject {
1130 value: value,
1131 node: SinglyLinkedListNode::new()
1132 })
1133 .unwrap()
1134 }
1135 }
1136
1137 generate_list_tests!(
1138 ref_ptr_tests,
1139 RefPtr<RefTestObject>,
1140 RefFactory<RefTestObject>,
1141 |p: &RefTestObject| p.value,
1142 |list: &mut SinglyLinkedList<RefPtr<RefTestObject>>, obj| list.push_front(obj)
1143 );
1144
1145 #[test]
1146 fn test_ref_ptr_identity() {
1147 let mut list = SinglyLinkedList::<RefPtr<RefTestObject>>::new();
1148 let obj =
1149 crate::make_ref_counted!(RefTestObject { value: 1, node: SinglyLinkedListNode::new() })
1150 .unwrap();
1151 list.push_front(obj.clone());
1152 let popped = list.pop_front().unwrap();
1153 assert!(RefPtr::ptr_eq(&popped, &obj));
1154 }
1155
1156 #[derive(crate::SinglyLinkedListContainable)]
1157 #[repr(C)]
1158 pub struct BaseItem {
1159 #[sll_node]
1160 node: SinglyLinkedListNode<BaseItem>,
1161 }
1162
1163 #[repr(C)]
1164 pub struct RustItem {
1165 base: BaseItem,
1166 value: i32,
1167 }
1168
1169 unsafe extern "C" {
1170 fn create_cpp_list() -> *mut c_void;
1171 fn destroy_cpp_list(list_ptr: *mut c_void);
1172 fn create_cpp_item(value: i32) -> *mut c_void;
1173 fn destroy_cpp_item(item_ptr: *mut c_void);
1174 fn list_push_front(list_ptr: *mut c_void, item_ptr: *mut c_void);
1175 fn list_pop_front(list_ptr: *mut c_void) -> *mut c_void;
1176 fn list_is_empty(list_ptr: *mut c_void) -> bool;
1177 fn get_cpp_item_value(item_ptr: *mut c_void) -> i32;
1178 }
1179
1180 #[test]
1181 #[cfg_attr(miri, ignore = "miri does not support calling foreign functions")]
1182 fn test_cross_lang_list() {
1183 use core::ffi::c_void;
1184
1185 unsafe {
1186 let list_ptr = create_cpp_list();
1187 assert!(list_is_empty(list_ptr));
1188
1189 let cpp_item1 = create_cpp_item(10);
1190 let cpp_item2 = create_cpp_item(20);
1191
1192 let mut rust_item =
1193 RustItem { base: BaseItem { node: SinglyLinkedListNode::new() }, value: 30 };
1194
1195 list_push_front(list_ptr, cpp_item1);
1197 assert!(!list_is_empty(list_ptr));
1198
1199 list_push_front(list_ptr, &mut rust_item.base as *mut BaseItem as *mut c_void);
1201
1202 list_push_front(list_ptr, cpp_item2);
1204
1205 let popped = list_pop_front(list_ptr);
1209 assert_eq!(get_cpp_item_value(popped), 20);
1210 destroy_cpp_item(popped);
1211
1212 let popped = list_pop_front(list_ptr);
1214 let popped_rust_item = popped as *mut RustItem; assert_eq!((*popped_rust_item).value, 30);
1216
1217 let popped = list_pop_front(list_ptr);
1219 assert_eq!(get_cpp_item_value(popped), 10);
1220 destroy_cpp_item(popped);
1221
1222 assert!(list_is_empty(list_ptr));
1223 destroy_cpp_list(list_ptr);
1224 }
1225 }
1226
1227 struct Tag2;
1228
1229 #[fbl::ref_counted]
1230 #[derive(crate::SinglyLinkedListContainable, crate::Recyclable)]
1231 #[repr(C)]
1232 struct MultiListObject {
1233 value: i32,
1234 #[sll_node]
1235 node1: SinglyLinkedListNode<MultiListObject>,
1236 node2: SinglyLinkedListNode<MultiListObject>,
1237 }
1238
1239 impl SinglyLinkedListContainable<MultiListObject, Tag2> for MultiListObject {
1240 fn get_node(&self) -> &SinglyLinkedListNode<MultiListObject> {
1241 &self.node2
1242 }
1243 }
1244
1245 #[test]
1246 fn test_multiple_lists() {
1247 let mut list1 = SinglyLinkedList::<RefPtr<MultiListObject>, DefaultObjectTag>::new();
1248 let mut list2 = SinglyLinkedList::<RefPtr<MultiListObject>, Tag2>::new();
1249
1250 let obj1 = fbl::make_ref_counted!(MultiListObject {
1251 value: 1,
1252 node1: SinglyLinkedListNode::new(),
1253 node2: SinglyLinkedListNode::new(),
1254 })
1255 .unwrap();
1256
1257 let obj2 = fbl::make_ref_counted!(MultiListObject {
1258 value: 2,
1259 node1: SinglyLinkedListNode::new(),
1260 node2: SinglyLinkedListNode::new(),
1261 })
1262 .unwrap();
1263
1264 list1.push_front(obj1.clone());
1265 list1.push_front(obj2.clone());
1266
1267 list2.push_front(obj1.clone());
1268
1269 let mut iter1 = list1.iter();
1270 assert_eq!(iter1.next().unwrap().value, 2);
1271 assert_eq!(iter1.next().unwrap().value, 1);
1272 assert!(iter1.next().is_none());
1273
1274 let mut iter2 = list2.iter();
1275 assert_eq!(iter2.next().unwrap().value, 1);
1276 assert!(iter2.next().is_none());
1277
1278 assert_eq!(list1.pop_front().unwrap().value, 2);
1279 assert_eq!(list2.pop_front().unwrap().value, 1);
1280
1281 assert!(!list1.is_empty());
1282 assert!(list2.is_empty());
1283
1284 assert_eq!(list1.pop_front().unwrap().value, 1);
1285 assert!(list1.is_empty());
1286 }
1287
1288 #[test]
1289 fn test_size_tracking() {
1290 let mut list =
1291 SinglyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new();
1292
1293 assert_eq!(list.size(), 0);
1294 list.push_front(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1295 assert_eq!(list.size(), 1);
1296 list.push_front(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1297 assert_eq!(list.size(), 2);
1298
1299 list.pop_front();
1300 assert_eq!(list.size(), 1);
1301 list.clear();
1302 }
1303
1304 #[test]
1305 fn test_split_after_size_tracking() {
1306 let mut list = SinglyLinkedList::<*mut TestObject, DefaultObjectTag, TrackingSize>::new();
1307 let mut obj1 = TestObject::new(1);
1308 let mut obj2 = TestObject::new(2);
1309 let mut obj3 = TestObject::new(3);
1310
1311 unsafe {
1312 list.push_front_raw(&mut obj1);
1313 list.push_front_raw(&mut obj2);
1314 list.push_front_raw(&mut obj3);
1315 }
1316
1317 assert_eq!(list.size(), 3);
1318
1319 let raw_pos = {
1320 let found = list.find_if(|o| o.value == 2).unwrap();
1321 found as *const TestObject as *mut TestObject
1322 };
1323
1324 let mut other = unsafe { list.split_after_raw(raw_pos) };
1325
1326 assert_eq!(list.size(), 2);
1327 assert_eq!(other.size(), 1);
1328
1329 list.clear();
1330 other.clear();
1331 }
1332
1333 #[test]
1334 fn test_lifecycle_on_drop() {
1335 let mut list = SinglyLinkedList::<UniquePtr<UniqueTestObject>>::new();
1336 let obj1 = UniquePtr::try_new(UniqueTestObject::new(1)).unwrap();
1337 let obj2 = UniquePtr::try_new(UniqueTestObject::new(2)).unwrap();
1338
1339 list.push_front(obj1);
1340 list.push_front(obj2);
1341
1342 drop(list);
1343 }
1344
1345 #[derive(crate::SinglyLinkedListContainable)]
1346 struct DerivedObject {
1347 value: i32,
1348 #[sll_node]
1349 node: SinglyLinkedListNode<DerivedObject>,
1350 }
1351
1352 impl DerivedObject {
1353 fn new(value: i32) -> Self {
1354 Self { value, node: SinglyLinkedListNode::new() }
1355 }
1356 }
1357
1358 #[test]
1359 fn test_derive_containable() {
1360 let mut list = SinglyLinkedList::<*mut DerivedObject>::new();
1361 let mut obj1 = DerivedObject::new(1);
1362 let mut obj2 = DerivedObject::new(2);
1363
1364 unsafe {
1365 list.push_front_raw(&mut obj1);
1366 list.push_front_raw(&mut obj2);
1367 }
1368
1369 let mut iter = list.iter();
1370 assert_eq!(iter.next().unwrap().value, 2);
1371 assert_eq!(iter.next().unwrap().value, 1);
1372 assert!(iter.next().is_none());
1373 list.clear();
1374 }
1375
1376 struct Tag3;
1377
1378 #[derive(crate::SinglyLinkedListContainable)]
1379 struct MultiDerivedObject {
1380 value: i32,
1381 #[sll_node]
1382 node1: SinglyLinkedListNode<MultiDerivedObject>,
1383 #[sll_node(tag = Tag3)]
1384 node2: SinglyLinkedListNode<MultiDerivedObject>,
1385 }
1386
1387 impl MultiDerivedObject {
1388 fn new(value: i32) -> Self {
1389 Self { value, node1: SinglyLinkedListNode::new(), node2: SinglyLinkedListNode::new() }
1390 }
1391 }
1392
1393 #[test]
1394 fn test_derive_containable_multi() {
1395 let mut list1 = SinglyLinkedList::<*mut MultiDerivedObject, DefaultObjectTag>::new();
1396 let mut list2 = SinglyLinkedList::<*mut MultiDerivedObject, Tag3>::new();
1397
1398 let mut obj1 = MultiDerivedObject::new(1);
1399 let mut obj2 = MultiDerivedObject::new(2);
1400
1401 unsafe {
1402 list1.push_front_raw(core::ptr::addr_of_mut!(obj1));
1403 list1.push_front_raw(core::ptr::addr_of_mut!(obj2));
1404
1405 list2.push_front_raw(core::ptr::addr_of_mut!(obj1));
1406 }
1407
1408 let mut iter1 = list1.iter();
1409 assert_eq!(iter1.next().unwrap().value, 2);
1410 assert_eq!(iter1.next().unwrap().value, 1);
1411
1412 let mut iter2 = list2.iter();
1413 assert_eq!(iter2.next().unwrap().value, 1);
1414
1415 list1.clear();
1416 list2.clear();
1417 }
1418
1419 #[test]
1420 fn test_retain() {
1421 let mut list = SinglyLinkedList::<UniquePtr<UniqueTestObject>>::new();
1422 list.push_front(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1423 list.push_front(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1424 list.push_front(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1425
1426 list.retain(|o| o.value % 2 != 0);
1427
1428 let mut iter = list.iter();
1429 assert_eq!(iter.next().unwrap().value, 1);
1430 assert_eq!(iter.next().unwrap().value, 3);
1431 assert!(iter.next().is_none());
1432 list.clear();
1433 }
1434
1435 #[test]
1436 fn test_cursor_mut() {
1437 let mut list = SinglyLinkedList::<UniquePtr<UniqueTestObject>>::new();
1438 let obj1 = UniquePtr::try_new(UniqueTestObject::new(1)).unwrap();
1439 let obj2 = UniquePtr::try_new(UniqueTestObject::new(2)).unwrap();
1440 let obj3 = UniquePtr::try_new(UniqueTestObject::new(3)).unwrap();
1441
1442 list.push_front(obj1);
1443 list.push_front(obj2);
1444
1445 let mut cursor = list.cursor_mut();
1446 assert_eq!(cursor.get().unwrap().value, 2);
1447
1448 cursor.insert_after(obj3);
1449
1450 assert!(cursor.move_next());
1451 assert_eq!(cursor.get().unwrap().value, 3);
1452
1453 assert!(cursor.move_next());
1454 assert_eq!(cursor.get().unwrap().value, 1);
1455
1456 assert!(!cursor.move_next());
1457
1458 let mut cursor = list.cursor_mut();
1460 assert_eq!(cursor.get().unwrap().value, 2);
1461
1462 let erased = cursor.erase_next().unwrap();
1463 assert_eq!(erased.value, 3);
1464
1465 assert!(cursor.move_next());
1466 assert_eq!(cursor.get().unwrap().value, 1);
1467
1468 assert!(!cursor.move_next());
1469 }
1470
1471 #[test]
1472 fn test_iterator_from_element() {
1473 let mut list = SinglyLinkedList::<UniquePtr<UniqueTestObject>>::new();
1474 list.push_front(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1475 list.push_front(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1476 list.push_front(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1477
1478 let mut iter = list.iter();
1479 iter.next(); let obj2_ref = iter.next().unwrap();
1481
1482 let mut from_element_iter: Iterator<'_, UniquePtr<UniqueTestObject>> =
1483 Iterator::from_element(obj2_ref);
1484 assert_eq!(from_element_iter.next().unwrap().value, 2);
1485 assert_eq!(from_element_iter.next().unwrap().value, 3);
1486 assert!(from_element_iter.next().is_none());
1487
1488 list.clear();
1489 }
1490
1491 #[test]
1492 fn test_front_ops() {
1493 let mut list = SinglyLinkedList::<UniquePtr<UniqueTestObject>>::new();
1494 assert!(list.front().is_none());
1495
1496 list.push_front(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1497 assert_eq!(list.front().unwrap().value, 1);
1498
1499 list.push_front(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1500 assert_eq!(list.front().unwrap().value, 2);
1501
1502 list.clear();
1503 }
1504
1505 unsafe extern "C" {
1507 fn cpp_sll_create_unique_list() -> *mut c_void;
1509 fn cpp_sll_destroy_unique_list(list: *mut c_void);
1510 fn cpp_sll_unique_list_push_front(list: *mut c_void, item: *mut c_void);
1511 fn cpp_sll_unique_list_pop_front(list: *mut c_void) -> *mut c_void;
1512 fn cpp_sll_unique_list_is_empty(list: *mut c_void) -> bool;
1513
1514 fn cpp_sll_create_ref_list() -> *mut c_void;
1516 fn cpp_sll_destroy_ref_list(list: *mut c_void);
1517 fn cpp_sll_ref_list_push_front(list: *mut c_void, item: *mut c_void);
1518 fn cpp_sll_ref_list_pop_front(list: *mut c_void) -> *mut c_void;
1519 fn cpp_sll_ref_list_is_empty(list: *mut c_void) -> bool;
1520
1521 fn cpp_create_unique_object(value: i32, destruction_flag: *mut bool) -> *mut c_void;
1523 fn cpp_get_unique_object_value(obj: *mut c_void) -> i32;
1524
1525 fn cpp_create_ref_object(value: i32, destruction_flag: *mut bool) -> *mut c_void;
1527 fn cpp_get_ref_object_value(obj: *mut c_void) -> i32;
1528 }
1529
1530 #[test]
1531 #[cfg_attr(miri, ignore = "miri does not support calling foreign functions")]
1532 fn test_interop_rust_list_cpp_unique_objects() {
1533 let destroyed1 = AtomicBool::new(false);
1534 let destroyed2 = AtomicBool::new(false);
1535
1536 unsafe {
1537 let mut list = SinglyLinkedList::<UniquePtr<SharedUniqueObject>>::new();
1538
1539 let cpp_raw1 = cpp_create_unique_object(1, destroyed1.as_ptr() as *mut bool);
1540 let cpp_raw2 = cpp_create_unique_object(2, destroyed2.as_ptr() as *mut bool);
1541
1542 let obj1 = UniquePtr::from_raw(cpp_raw1 as *mut SharedUniqueObject);
1543 let obj2 = UniquePtr::from_raw(cpp_raw2 as *mut SharedUniqueObject);
1544
1545 list.push_front(obj1);
1546 list.push_front(obj2);
1547
1548 assert!(!destroyed1.load(Ordering::Relaxed));
1549 assert!(!destroyed2.load(Ordering::Relaxed));
1550
1551 let popped = list.pop_front();
1553 assert!(popped.is_some());
1554 assert_eq!(popped.as_ref().unwrap().value, 2);
1555
1556 drop(popped);
1558 assert!(!destroyed1.load(Ordering::Relaxed));
1559 assert!(destroyed2.load(Ordering::Relaxed));
1560
1561 }
1563 assert!(destroyed1.load(Ordering::Relaxed));
1564 }
1565
1566 #[test]
1567 #[cfg_attr(miri, ignore = "miri does not support calling foreign functions")]
1568 fn test_interop_cpp_list_rust_unique_objects() {
1569 let destroyed1 = Arc::new(AtomicBool::new(false));
1570 let destroyed2 = Arc::new(AtomicBool::new(false));
1571
1572 unsafe {
1573 let cpp_list = cpp_sll_create_unique_list();
1574 assert!(cpp_sll_unique_list_is_empty(cpp_list));
1575
1576 let obj1 = UniquePtr::try_new(SharedUniqueObject::new(1)).unwrap();
1577 let obj2 = UniquePtr::try_new(SharedUniqueObject::new(2)).unwrap();
1578
1579 let raw1 = UniquePtr::as_ptr(&obj1) as *mut SharedUniqueObject;
1581 (*raw1).destruction_flag = destroyed1.as_ptr() as *mut bool;
1582 let raw2 = UniquePtr::as_ptr(&obj2) as *mut SharedUniqueObject;
1583 (*raw2).destruction_flag = destroyed2.as_ptr() as *mut bool;
1584
1585 cpp_sll_unique_list_push_front(cpp_list, UniquePtr::into_raw(obj1) as *mut c_void);
1587 cpp_sll_unique_list_push_front(cpp_list, UniquePtr::into_raw(obj2) as *mut c_void);
1588
1589 assert!(!destroyed1.load(Ordering::Relaxed));
1590 assert!(!destroyed2.load(Ordering::Relaxed));
1591
1592 let popped = cpp_sll_unique_list_pop_front(cpp_list);
1594 assert!(!popped.is_null());
1595 assert_eq!(cpp_get_unique_object_value(popped), 2);
1596
1597 let popped_rust = UniquePtr::from_raw(popped as *mut SharedUniqueObject);
1599 drop(popped_rust);
1600 assert!(!destroyed1.load(Ordering::Relaxed));
1601 assert!(destroyed2.load(Ordering::Relaxed));
1602
1603 cpp_sll_destroy_unique_list(cpp_list);
1605 }
1606 assert!(destroyed1.load(Ordering::Relaxed));
1607 }
1608
1609 #[test]
1610 #[cfg_attr(miri, ignore = "miri does not support calling foreign functions")]
1611 fn test_interop_rust_list_cpp_ref_objects() {
1612 let destroyed1 = AtomicBool::new(false);
1613 let destroyed2 = AtomicBool::new(false);
1614
1615 unsafe {
1616 let mut list = SinglyLinkedList::<RefPtr<SharedRefObject>>::new();
1617
1618 let cpp_raw1 = cpp_create_ref_object(1, destroyed1.as_ptr() as *mut bool);
1619 let cpp_raw2 = cpp_create_ref_object(2, destroyed2.as_ptr() as *mut bool);
1620
1621 let obj1 = RefPtr::from_raw(cpp_raw1 as *mut SharedRefObject);
1622 let obj2 = RefPtr::from_raw(cpp_raw2 as *mut SharedRefObject);
1623
1624 list.push_front(obj1);
1625 list.push_front(obj2);
1626
1627 assert!(!destroyed1.load(Ordering::Relaxed));
1628 assert!(!destroyed2.load(Ordering::Relaxed));
1629
1630 let popped = list.pop_front();
1632 assert!(popped.is_some());
1633 assert_eq!(popped.as_ref().unwrap().value, 2);
1634
1635 drop(popped);
1637 assert!(!destroyed1.load(Ordering::Relaxed));
1638 assert!(destroyed2.load(Ordering::Relaxed));
1639
1640 }
1642 assert!(destroyed1.load(Ordering::Relaxed));
1643 }
1644
1645 #[test]
1646 #[cfg_attr(miri, ignore = "miri does not support calling foreign functions")]
1647 fn test_interop_cpp_list_rust_ref_objects() {
1648 let destroyed1 = Arc::new(AtomicBool::new(false));
1649 let destroyed2 = Arc::new(AtomicBool::new(false));
1650
1651 unsafe {
1652 let cpp_list = cpp_sll_create_ref_list();
1653 assert!(cpp_sll_ref_list_is_empty(cpp_list));
1654
1655 let obj1 = SharedRefObject::new_ref_counted(1);
1656 let obj2 = SharedRefObject::new_ref_counted(2);
1657
1658 let raw1 = RefPtr::as_ptr(&obj1) as *mut SharedRefObject;
1660 (*raw1).destruction_flag = destroyed1.as_ptr() as *mut bool;
1661 let raw2 = RefPtr::as_ptr(&obj2) as *mut SharedRefObject;
1662 (*raw2).destruction_flag = destroyed2.as_ptr() as *mut bool;
1663
1664 cpp_sll_ref_list_push_front(
1666 cpp_list,
1667 RefPtr::into_raw(obj1) as *mut SharedRefObject as *mut c_void,
1668 );
1669 cpp_sll_ref_list_push_front(
1670 cpp_list,
1671 RefPtr::into_raw(obj2) as *mut SharedRefObject as *mut c_void,
1672 );
1673
1674 assert!(!destroyed1.load(Ordering::Relaxed));
1675 assert!(!destroyed2.load(Ordering::Relaxed));
1676
1677 let popped = cpp_sll_ref_list_pop_front(cpp_list);
1679 assert!(!popped.is_null());
1680 assert_eq!(cpp_get_ref_object_value(popped), 2);
1681
1682 let popped_rust = RefPtr::from_raw(popped as *mut SharedRefObject);
1684 drop(popped_rust);
1685 assert!(!destroyed1.load(Ordering::Relaxed));
1686 assert!(destroyed2.load(Ordering::Relaxed));
1687
1688 cpp_sll_destroy_ref_list(cpp_list);
1690 }
1691 assert!(destroyed1.load(Ordering::Relaxed));
1692 }
1693}