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::<SinglyLinkedListNode<()>>() == core::mem::size_of::<*mut ()>()
769 );
770 zr::static_assert!(
771 core::mem::align_of::<SinglyLinkedListNode<()>>() == core::mem::align_of::<*mut ()>()
772 );
773
774 zr::static_assert!(
775 core::mem::size_of::<SinglyLinkedList<*mut DummyTarget>>()
776 == core::mem::size_of::<*mut DummyTarget>()
777 );
778 zr::static_assert!(
779 core::mem::align_of::<SinglyLinkedList<*mut DummyTarget>>()
780 == core::mem::align_of::<*mut DummyTarget>()
781 );
782
783 zr::static_assert!(
784 core::mem::size_of::<SinglyLinkedList<*mut DummyTarget, DefaultObjectTag, TrackingSize>>()
785 == 2 * core::mem::size_of::<*mut DummyTarget>()
786 );
787 zr::static_assert!(
788 core::mem::align_of::<SinglyLinkedList<*mut DummyTarget, DefaultObjectTag, TrackingSize>>()
789 == core::mem::align_of::<*mut DummyTarget>()
790 );
791
792 zr::static_assert!(
793 core::mem::size_of::<Iterator<'_, *mut DummyTarget>>()
794 == core::mem::size_of::<*mut DummyTarget>()
795 );
796 zr::static_assert!(
797 core::mem::align_of::<Iterator<'_, *mut DummyTarget>>()
798 == core::mem::align_of::<*mut DummyTarget>()
799 );
800
801 macro_rules! generate_list_tests {
802 ($mod_name:ident, $ptr_type:ty, $factory_type:ty, $get_val:expr, $push:expr) => {
803 mod $mod_name {
804 use super::*;
805
806 #[test]
807 fn test_basic_ops() {
808 let mut factory = <$factory_type>::new();
809 let mut list = SinglyLinkedList::<$ptr_type>::new();
810 assert!(list.is_empty());
811
812 let obj1 = factory.create(1);
813 let obj2 = factory.create(2);
814 let obj3 = factory.create(3);
815
816 $push(&mut list, obj1);
817 $push(&mut list, obj2);
818 $push(&mut list, obj3);
819
820 assert!(!list.is_empty());
821
822 let mut iter = list.iter();
823 assert_eq!(iter.next().unwrap().value, 3);
824 assert_eq!(iter.next().unwrap().value, 2);
825 assert_eq!(iter.next().unwrap().value, 1);
826 assert!(iter.next().is_none());
827
828 assert_eq!($get_val(list.pop_front().unwrap().get_ref()), 3);
829 assert_eq!($get_val(list.pop_front().unwrap().get_ref()), 2);
830 assert_eq!($get_val(list.pop_front().unwrap().get_ref()), 1);
831
832 assert!(list.is_empty());
833 }
834
835 #[test]
836 fn test_insert_after() {
837 let mut factory = <$factory_type>::new();
838 let mut list = SinglyLinkedList::<$ptr_type>::new();
839
840 let obj1 = factory.create(1);
841 let raw1 = <$ptr_type as PtrTraits>::into_raw(obj1);
842 $push(&mut list, unsafe { <$ptr_type as PtrTraits>::from_raw(raw1) });
843
844 let obj2 = factory.create(2);
845 let raw2 = <$ptr_type as PtrTraits>::into_raw(obj2);
846 unsafe {
847 list.insert_after_raw(raw1, <$ptr_type as PtrTraits>::from_raw(raw2));
848 }
849
850 let obj3 = factory.create(3);
851 unsafe {
852 list.insert_after_raw(raw2, obj3);
853 }
854
855 let mut iter = list.iter();
856 assert_eq!(iter.next().unwrap().value, 1);
857 assert_eq!(iter.next().unwrap().value, 2);
858 assert_eq!(iter.next().unwrap().value, 3);
859 assert!(iter.next().is_none());
860
861 list.clear();
863 }
864
865 #[test]
866 fn test_clear() {
867 let mut factory = <$factory_type>::new();
868 let mut list = SinglyLinkedList::<$ptr_type>::new();
869 let obj1 = factory.create(1);
870 let obj2 = factory.create(2);
871
872 $push(&mut list, obj1);
873 $push(&mut list, obj2);
874
875 assert!(!list.is_empty());
876 list.clear();
877 assert!(list.is_empty());
878 }
879
880 #[test]
881 fn test_erase_next() {
882 let mut factory = <$factory_type>::new();
883 let mut list = SinglyLinkedList::<$ptr_type>::new();
884
885 let obj1 = factory.create(1);
886 let raw1 = <$ptr_type as PtrTraits>::into_raw(obj1);
887 $push(&mut list, unsafe { <$ptr_type as PtrTraits>::from_raw(raw1) });
888
889 let obj2 = factory.create(2);
890 let raw2 = <$ptr_type as PtrTraits>::into_raw(obj2);
891 unsafe {
892 list.insert_after_raw(raw1, <$ptr_type as PtrTraits>::from_raw(raw2));
893 }
894
895 let obj3 = factory.create(3);
896 unsafe {
897 list.insert_after_raw(raw2, obj3);
898 }
899
900 let erased = unsafe { list.erase_next_raw(raw1) };
901 assert_eq!($get_val(erased.unwrap().get_ref()), 2);
902
903 let mut iter = list.iter();
904 assert_eq!(iter.next().unwrap().value, 1);
905 assert_eq!(iter.next().unwrap().value, 3);
906 assert!(iter.next().is_none());
907
908 list.clear();
910 }
911
912 #[test]
913 fn test_swap() {
914 let mut factory = <$factory_type>::new();
915 let mut list1 = SinglyLinkedList::<$ptr_type>::new();
916 let mut list2 = SinglyLinkedList::<$ptr_type>::new();
917
918 let obj1 = factory.create(1);
919 let obj2 = factory.create(2);
920
921 $push(&mut list1, obj1);
922 $push(&mut list2, obj2);
923
924 list1.swap(&mut list2);
925
926 assert_eq!($get_val(list1.pop_front().unwrap().get_ref()), 2);
927 assert_eq!($get_val(list2.pop_front().unwrap().get_ref()), 1);
928 }
929
930 #[test]
931 fn test_size_slow() {
932 let mut factory = <$factory_type>::new();
933 let mut list = SinglyLinkedList::<$ptr_type>::new();
934 let obj1 = factory.create(1);
935 let obj2 = factory.create(2);
936
937 assert_eq!(list.size_slow(), 0);
938
939 $push(&mut list, obj1);
940 assert_eq!(list.size_slow(), 1);
941 $push(&mut list, obj2);
942 assert_eq!(list.size_slow(), 2);
943
944 list.pop_front();
945 assert_eq!(list.size_slow(), 1);
946
947 list.pop_front();
948 assert_eq!(list.size_slow(), 0);
949 }
950
951 #[test]
952 fn test_find_if() {
953 let mut factory = <$factory_type>::new();
954 let mut list = SinglyLinkedList::<$ptr_type>::new();
955 let obj1 = factory.create(1);
956 let obj2 = factory.create(2);
957
958 $push(&mut list, obj1);
959 $push(&mut list, obj2);
960
961 let found = list.find_if(|o| o.value == 1);
962 assert!(found.is_some());
963 assert_eq!(found.unwrap().value, 1);
964
965 let found = list.find_if(|o| o.value == 3);
966 assert!(found.is_none());
967
968 list.clear();
970 }
971
972 #[test]
973 fn test_erase_if() {
974 let mut factory = <$factory_type>::new();
975 let mut list = SinglyLinkedList::<$ptr_type>::new();
976 let obj1 = factory.create(1);
977 let obj2 = factory.create(2);
978 let obj3 = factory.create(3);
979
980 $push(&mut list, obj1);
981 $push(&mut list, obj2);
982 $push(&mut list, obj3);
983
984 let erased = list.erase_if(|o| o.value == 2);
987 assert!(erased.is_some());
988 assert_eq!($get_val(erased.unwrap().get_ref()), 2);
989
990 let mut iter = list.iter();
991 assert_eq!(iter.next().unwrap().value, 3);
992 assert_eq!(iter.next().unwrap().value, 1);
993 assert!(iter.next().is_none());
994
995 list.clear();
997 }
998
999 #[test]
1000 fn test_replace_if() {
1001 let mut factory = <$factory_type>::new();
1002 let mut list = SinglyLinkedList::<$ptr_type>::new();
1003 let obj1 = factory.create(1);
1004 let obj2 = factory.create(2);
1005 let obj3 = factory.create(3);
1006
1007 $push(&mut list, obj1);
1008 $push(&mut list, obj2);
1009
1010 let replaced = unsafe { list.replace_if_raw(|o| o.value == 2, obj3) };
1013 assert_eq!($get_val(replaced.unwrap().get_ref()), 2);
1014
1015 let mut iter = list.iter();
1016 assert_eq!(iter.next().unwrap().value, 3);
1017 assert_eq!(iter.next().unwrap().value, 1);
1018 assert!(iter.next().is_none());
1019
1020 list.clear();
1022 }
1023
1024 #[test]
1025 fn test_split_after() {
1026 let mut factory = <$factory_type>::new();
1027 let mut list = SinglyLinkedList::<$ptr_type>::new();
1028 let obj1 = factory.create(1);
1029 let obj2 = factory.create(2);
1030 let obj3 = factory.create(3);
1031
1032 $push(&mut list, obj1);
1033 $push(&mut list, obj2);
1034 $push(&mut list, obj3);
1035
1036 let raw_pos = {
1039 let found = list.find_if(|o| o.value == 2).unwrap();
1040 found as *const <$ptr_type as PtrTraits>::Target
1041 as *mut <$ptr_type as PtrTraits>::Target
1042 };
1043
1044 let mut other = unsafe { list.split_after_raw(raw_pos) };
1045
1046 assert_eq!(list.size_slow(), 2);
1050 assert_eq!(other.size_slow(), 1);
1051
1052 let mut iter = list.iter();
1053 assert_eq!(iter.next().unwrap().value, 3);
1054 assert_eq!(iter.next().unwrap().value, 2);
1055 assert!(iter.next().is_none());
1056
1057 let mut iter = other.iter();
1058 assert_eq!(iter.next().unwrap().value, 1);
1059 assert!(iter.next().is_none());
1060
1061 list.clear();
1063 other.clear();
1064 }
1065 }
1066 };
1067 }
1068
1069 #[derive(fbl::Recyclable, crate::SinglyLinkedListContainable)]
1070 struct TestObject {
1071 value: i32,
1072 #[sll_node]
1073 node: SinglyLinkedListNode<TestObject>,
1074 }
1075
1076 impl TestObject {
1077 fn new(value: i32) -> Self {
1078 Self { value, node: SinglyLinkedListNode::new() }
1079 }
1080 }
1081
1082 impl TestValue for TestObject {
1083 fn new(value: i32) -> Self {
1084 Self::new(value)
1085 }
1086 }
1087
1088 generate_list_tests!(
1089 raw_ptr_tests,
1090 *mut TestObject,
1091 RawFactory<TestObject>,
1092 |p: &TestObject| p.value,
1093 |list: &mut SinglyLinkedList<*mut TestObject>, obj| unsafe {
1094 list.push_front_raw(obj);
1095 }
1096 );
1097
1098 #[derive(fbl::Recyclable, crate::SinglyLinkedListContainable)]
1099 struct UniqueTestObject {
1100 value: i32,
1101 #[sll_node]
1102 node: SinglyLinkedListNode<UniqueTestObject>,
1103 }
1104
1105 impl UniqueTestObject {
1106 fn new(value: i32) -> Self {
1107 Self { value, node: SinglyLinkedListNode::new() }
1108 }
1109 }
1110
1111 impl TestValue for UniqueTestObject {
1112 fn new(value: i32) -> Self {
1113 Self::new(value)
1114 }
1115 }
1116
1117 generate_list_tests!(
1118 unique_ptr_tests,
1119 UniquePtr<UniqueTestObject>,
1120 UniqueFactory<UniqueTestObject>,
1121 |p: &UniqueTestObject| p.value,
1122 |list: &mut SinglyLinkedList<UniquePtr<UniqueTestObject>>, obj| list.push_front(obj)
1123 );
1124
1125 #[fbl::ref_counted]
1126 #[derive(crate::SinglyLinkedListContainable, crate::Recyclable)]
1127 #[repr(C)]
1128 pub struct RefTestObject {
1129 value: i32,
1130 #[sll_node]
1131 node: SinglyLinkedListNode<RefTestObject>,
1132 }
1133
1134 impl TestValue for RefTestObject {
1135 fn new_ref_counted(value: i32) -> RefPtr<Self> {
1136 crate::make_ref_counted!(RefTestObject {
1137 value: value,
1138 node: SinglyLinkedListNode::new()
1139 })
1140 .unwrap()
1141 }
1142 }
1143
1144 generate_list_tests!(
1145 ref_ptr_tests,
1146 RefPtr<RefTestObject>,
1147 RefFactory<RefTestObject>,
1148 |p: &RefTestObject| p.value,
1149 |list: &mut SinglyLinkedList<RefPtr<RefTestObject>>, obj| list.push_front(obj)
1150 );
1151
1152 #[test]
1153 fn test_ref_ptr_identity() {
1154 let mut list = SinglyLinkedList::<RefPtr<RefTestObject>>::new();
1155 let obj =
1156 crate::make_ref_counted!(RefTestObject { value: 1, node: SinglyLinkedListNode::new() })
1157 .unwrap();
1158 list.push_front(obj.clone());
1159 let popped = list.pop_front().unwrap();
1160 assert!(RefPtr::ptr_eq(&popped, &obj));
1161 }
1162
1163 #[derive(crate::SinglyLinkedListContainable)]
1164 #[repr(C)]
1165 pub struct BaseItem {
1166 #[sll_node]
1167 node: SinglyLinkedListNode<BaseItem>,
1168 }
1169
1170 #[repr(C)]
1171 pub struct RustItem {
1172 base: BaseItem,
1173 value: i32,
1174 }
1175
1176 unsafe extern "C" {
1177 fn create_cpp_list() -> *mut c_void;
1178 fn destroy_cpp_list(list_ptr: *mut c_void);
1179 fn create_cpp_item(value: i32) -> *mut c_void;
1180 fn destroy_cpp_item(item_ptr: *mut c_void);
1181 fn list_push_front(list_ptr: *mut c_void, item_ptr: *mut c_void);
1182 fn list_pop_front(list_ptr: *mut c_void) -> *mut c_void;
1183 fn list_is_empty(list_ptr: *mut c_void) -> bool;
1184 fn get_cpp_item_value(item_ptr: *mut c_void) -> i32;
1185 }
1186
1187 #[test]
1188 #[cfg_attr(miri, ignore = "miri does not support calling foreign functions")]
1189 fn test_cross_lang_list() {
1190 use core::ffi::c_void;
1191
1192 unsafe {
1193 let list_ptr = create_cpp_list();
1194 assert!(list_is_empty(list_ptr));
1195
1196 let cpp_item1 = create_cpp_item(10);
1197 let cpp_item2 = create_cpp_item(20);
1198
1199 let mut rust_item =
1200 RustItem { base: BaseItem { node: SinglyLinkedListNode::new() }, value: 30 };
1201
1202 list_push_front(list_ptr, cpp_item1);
1204 assert!(!list_is_empty(list_ptr));
1205
1206 list_push_front(list_ptr, &mut rust_item.base as *mut BaseItem as *mut c_void);
1208
1209 list_push_front(list_ptr, cpp_item2);
1211
1212 let popped = list_pop_front(list_ptr);
1216 assert_eq!(get_cpp_item_value(popped), 20);
1217 destroy_cpp_item(popped);
1218
1219 let popped = list_pop_front(list_ptr);
1221 let popped_rust_item = popped as *mut RustItem; assert_eq!((*popped_rust_item).value, 30);
1223
1224 let popped = list_pop_front(list_ptr);
1226 assert_eq!(get_cpp_item_value(popped), 10);
1227 destroy_cpp_item(popped);
1228
1229 assert!(list_is_empty(list_ptr));
1230 destroy_cpp_list(list_ptr);
1231 }
1232 }
1233
1234 struct Tag2;
1235
1236 #[fbl::ref_counted]
1237 #[derive(crate::SinglyLinkedListContainable, crate::Recyclable)]
1238 #[repr(C)]
1239 struct MultiListObject {
1240 value: i32,
1241 #[sll_node]
1242 node1: SinglyLinkedListNode<MultiListObject>,
1243 node2: SinglyLinkedListNode<MultiListObject>,
1244 }
1245
1246 impl SinglyLinkedListContainable<MultiListObject, Tag2> for MultiListObject {
1247 fn get_node(&self) -> &SinglyLinkedListNode<MultiListObject> {
1248 &self.node2
1249 }
1250 }
1251
1252 #[test]
1253 fn test_multiple_lists() {
1254 let mut list1 = SinglyLinkedList::<RefPtr<MultiListObject>, DefaultObjectTag>::new();
1255 let mut list2 = SinglyLinkedList::<RefPtr<MultiListObject>, Tag2>::new();
1256
1257 let obj1 = fbl::make_ref_counted!(MultiListObject {
1258 value: 1,
1259 node1: SinglyLinkedListNode::new(),
1260 node2: SinglyLinkedListNode::new(),
1261 })
1262 .unwrap();
1263
1264 let obj2 = fbl::make_ref_counted!(MultiListObject {
1265 value: 2,
1266 node1: SinglyLinkedListNode::new(),
1267 node2: SinglyLinkedListNode::new(),
1268 })
1269 .unwrap();
1270
1271 list1.push_front(obj1.clone());
1272 list1.push_front(obj2.clone());
1273
1274 list2.push_front(obj1.clone());
1275
1276 let mut iter1 = list1.iter();
1277 assert_eq!(iter1.next().unwrap().value, 2);
1278 assert_eq!(iter1.next().unwrap().value, 1);
1279 assert!(iter1.next().is_none());
1280
1281 let mut iter2 = list2.iter();
1282 assert_eq!(iter2.next().unwrap().value, 1);
1283 assert!(iter2.next().is_none());
1284
1285 assert_eq!(list1.pop_front().unwrap().value, 2);
1286 assert_eq!(list2.pop_front().unwrap().value, 1);
1287
1288 assert!(!list1.is_empty());
1289 assert!(list2.is_empty());
1290
1291 assert_eq!(list1.pop_front().unwrap().value, 1);
1292 assert!(list1.is_empty());
1293 }
1294
1295 #[test]
1296 fn test_size_tracking() {
1297 let mut list =
1298 SinglyLinkedList::<UniquePtr<UniqueTestObject>, DefaultObjectTag, TrackingSize>::new();
1299
1300 assert_eq!(list.size(), 0);
1301 list.push_front(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1302 assert_eq!(list.size(), 1);
1303 list.push_front(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1304 assert_eq!(list.size(), 2);
1305
1306 list.pop_front();
1307 assert_eq!(list.size(), 1);
1308 list.clear();
1309 }
1310
1311 #[test]
1312 fn test_split_after_size_tracking() {
1313 let mut list = SinglyLinkedList::<*mut TestObject, DefaultObjectTag, TrackingSize>::new();
1314 let mut obj1 = TestObject::new(1);
1315 let mut obj2 = TestObject::new(2);
1316 let mut obj3 = TestObject::new(3);
1317
1318 unsafe {
1319 list.push_front_raw(&mut obj1);
1320 list.push_front_raw(&mut obj2);
1321 list.push_front_raw(&mut obj3);
1322 }
1323
1324 assert_eq!(list.size(), 3);
1325
1326 let raw_pos = {
1327 let found = list.find_if(|o| o.value == 2).unwrap();
1328 found as *const TestObject as *mut TestObject
1329 };
1330
1331 let mut other = unsafe { list.split_after_raw(raw_pos) };
1332
1333 assert_eq!(list.size(), 2);
1334 assert_eq!(other.size(), 1);
1335
1336 list.clear();
1337 other.clear();
1338 }
1339
1340 #[test]
1341 fn test_lifecycle_on_drop() {
1342 let mut list = SinglyLinkedList::<UniquePtr<UniqueTestObject>>::new();
1343 let obj1 = UniquePtr::try_new(UniqueTestObject::new(1)).unwrap();
1344 let obj2 = UniquePtr::try_new(UniqueTestObject::new(2)).unwrap();
1345
1346 list.push_front(obj1);
1347 list.push_front(obj2);
1348
1349 drop(list);
1350 }
1351
1352 #[derive(crate::SinglyLinkedListContainable)]
1353 struct DerivedObject {
1354 value: i32,
1355 #[sll_node]
1356 node: SinglyLinkedListNode<DerivedObject>,
1357 }
1358
1359 impl DerivedObject {
1360 fn new(value: i32) -> Self {
1361 Self { value, node: SinglyLinkedListNode::new() }
1362 }
1363 }
1364
1365 #[test]
1366 fn test_derive_containable() {
1367 let mut list = SinglyLinkedList::<*mut DerivedObject>::new();
1368 let mut obj1 = DerivedObject::new(1);
1369 let mut obj2 = DerivedObject::new(2);
1370
1371 unsafe {
1372 list.push_front_raw(&mut obj1);
1373 list.push_front_raw(&mut obj2);
1374 }
1375
1376 let mut iter = list.iter();
1377 assert_eq!(iter.next().unwrap().value, 2);
1378 assert_eq!(iter.next().unwrap().value, 1);
1379 assert!(iter.next().is_none());
1380 list.clear();
1381 }
1382
1383 struct Tag3;
1384
1385 #[derive(crate::SinglyLinkedListContainable)]
1386 struct MultiDerivedObject {
1387 value: i32,
1388 #[sll_node]
1389 node1: SinglyLinkedListNode<MultiDerivedObject>,
1390 #[sll_node(tag = Tag3)]
1391 node2: SinglyLinkedListNode<MultiDerivedObject>,
1392 }
1393
1394 impl MultiDerivedObject {
1395 fn new(value: i32) -> Self {
1396 Self { value, node1: SinglyLinkedListNode::new(), node2: SinglyLinkedListNode::new() }
1397 }
1398 }
1399
1400 #[test]
1401 fn test_derive_containable_multi() {
1402 let mut list1 = SinglyLinkedList::<*mut MultiDerivedObject, DefaultObjectTag>::new();
1403 let mut list2 = SinglyLinkedList::<*mut MultiDerivedObject, Tag3>::new();
1404
1405 let mut obj1 = MultiDerivedObject::new(1);
1406 let mut obj2 = MultiDerivedObject::new(2);
1407
1408 unsafe {
1409 list1.push_front_raw(core::ptr::addr_of_mut!(obj1));
1410 list1.push_front_raw(core::ptr::addr_of_mut!(obj2));
1411
1412 list2.push_front_raw(core::ptr::addr_of_mut!(obj1));
1413 }
1414
1415 let mut iter1 = list1.iter();
1416 assert_eq!(iter1.next().unwrap().value, 2);
1417 assert_eq!(iter1.next().unwrap().value, 1);
1418
1419 let mut iter2 = list2.iter();
1420 assert_eq!(iter2.next().unwrap().value, 1);
1421
1422 list1.clear();
1423 list2.clear();
1424 }
1425
1426 #[test]
1427 fn test_retain() {
1428 let mut list = SinglyLinkedList::<UniquePtr<UniqueTestObject>>::new();
1429 list.push_front(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1430 list.push_front(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1431 list.push_front(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1432
1433 list.retain(|o| o.value % 2 != 0);
1434
1435 let mut iter = list.iter();
1436 assert_eq!(iter.next().unwrap().value, 1);
1437 assert_eq!(iter.next().unwrap().value, 3);
1438 assert!(iter.next().is_none());
1439 list.clear();
1440 }
1441
1442 #[test]
1443 fn test_cursor_mut() {
1444 let mut list = SinglyLinkedList::<UniquePtr<UniqueTestObject>>::new();
1445 let obj1 = UniquePtr::try_new(UniqueTestObject::new(1)).unwrap();
1446 let obj2 = UniquePtr::try_new(UniqueTestObject::new(2)).unwrap();
1447 let obj3 = UniquePtr::try_new(UniqueTestObject::new(3)).unwrap();
1448
1449 list.push_front(obj1);
1450 list.push_front(obj2);
1451
1452 let mut cursor = list.cursor_mut();
1453 assert_eq!(cursor.get().unwrap().value, 2);
1454
1455 cursor.insert_after(obj3);
1456
1457 assert!(cursor.move_next());
1458 assert_eq!(cursor.get().unwrap().value, 3);
1459
1460 assert!(cursor.move_next());
1461 assert_eq!(cursor.get().unwrap().value, 1);
1462
1463 assert!(!cursor.move_next());
1464
1465 let mut cursor = list.cursor_mut();
1467 assert_eq!(cursor.get().unwrap().value, 2);
1468
1469 let erased = cursor.erase_next().unwrap();
1470 assert_eq!(erased.value, 3);
1471
1472 assert!(cursor.move_next());
1473 assert_eq!(cursor.get().unwrap().value, 1);
1474
1475 assert!(!cursor.move_next());
1476 }
1477
1478 #[test]
1479 fn test_iterator_from_element() {
1480 let mut list = SinglyLinkedList::<UniquePtr<UniqueTestObject>>::new();
1481 list.push_front(UniquePtr::try_new(UniqueTestObject::new(3)).unwrap());
1482 list.push_front(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1483 list.push_front(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1484
1485 let mut iter = list.iter();
1486 iter.next(); let obj2_ref = iter.next().unwrap();
1488
1489 let mut from_element_iter: Iterator<'_, UniquePtr<UniqueTestObject>> =
1490 Iterator::from_element(obj2_ref);
1491 assert_eq!(from_element_iter.next().unwrap().value, 2);
1492 assert_eq!(from_element_iter.next().unwrap().value, 3);
1493 assert!(from_element_iter.next().is_none());
1494
1495 list.clear();
1496 }
1497
1498 #[test]
1499 fn test_front_ops() {
1500 let mut list = SinglyLinkedList::<UniquePtr<UniqueTestObject>>::new();
1501 assert!(list.front().is_none());
1502
1503 list.push_front(UniquePtr::try_new(UniqueTestObject::new(1)).unwrap());
1504 assert_eq!(list.front().unwrap().value, 1);
1505
1506 list.push_front(UniquePtr::try_new(UniqueTestObject::new(2)).unwrap());
1507 assert_eq!(list.front().unwrap().value, 2);
1508
1509 list.clear();
1510 }
1511
1512 unsafe extern "C" {
1514 fn cpp_sll_create_unique_list() -> *mut c_void;
1516 fn cpp_sll_destroy_unique_list(list: *mut c_void);
1517 fn cpp_sll_unique_list_push_front(list: *mut c_void, item: *mut c_void);
1518 fn cpp_sll_unique_list_pop_front(list: *mut c_void) -> *mut c_void;
1519 fn cpp_sll_unique_list_is_empty(list: *mut c_void) -> bool;
1520
1521 fn cpp_sll_create_ref_list() -> *mut c_void;
1523 fn cpp_sll_destroy_ref_list(list: *mut c_void);
1524 fn cpp_sll_ref_list_push_front(list: *mut c_void, item: *mut c_void);
1525 fn cpp_sll_ref_list_pop_front(list: *mut c_void) -> *mut c_void;
1526 fn cpp_sll_ref_list_is_empty(list: *mut c_void) -> bool;
1527
1528 fn cpp_create_unique_object(value: i32, destruction_flag: *mut bool) -> *mut c_void;
1530 fn cpp_get_unique_object_value(obj: *mut c_void) -> i32;
1531
1532 fn cpp_create_ref_object(value: i32, destruction_flag: *mut bool) -> *mut c_void;
1534 fn cpp_get_ref_object_value(obj: *mut c_void) -> i32;
1535 }
1536
1537 #[test]
1538 #[cfg_attr(miri, ignore = "miri does not support calling foreign functions")]
1539 fn test_interop_rust_list_cpp_unique_objects() {
1540 let destroyed1 = AtomicBool::new(false);
1541 let destroyed2 = AtomicBool::new(false);
1542
1543 unsafe {
1544 let mut list = SinglyLinkedList::<UniquePtr<SharedUniqueObject>>::new();
1545
1546 let cpp_raw1 = cpp_create_unique_object(1, destroyed1.as_ptr() as *mut bool);
1547 let cpp_raw2 = cpp_create_unique_object(2, destroyed2.as_ptr() as *mut bool);
1548
1549 let obj1 = UniquePtr::from_raw(cpp_raw1 as *mut SharedUniqueObject);
1550 let obj2 = UniquePtr::from_raw(cpp_raw2 as *mut SharedUniqueObject);
1551
1552 list.push_front(obj1);
1553 list.push_front(obj2);
1554
1555 assert!(!destroyed1.load(Ordering::Relaxed));
1556 assert!(!destroyed2.load(Ordering::Relaxed));
1557
1558 let popped = list.pop_front();
1560 assert!(popped.is_some());
1561 assert_eq!(popped.as_ref().unwrap().value, 2);
1562
1563 drop(popped);
1565 assert!(!destroyed1.load(Ordering::Relaxed));
1566 assert!(destroyed2.load(Ordering::Relaxed));
1567
1568 }
1570 assert!(destroyed1.load(Ordering::Relaxed));
1571 }
1572
1573 #[test]
1574 #[cfg_attr(miri, ignore = "miri does not support calling foreign functions")]
1575 fn test_interop_cpp_list_rust_unique_objects() {
1576 let destroyed1 = Arc::new(AtomicBool::new(false));
1577 let destroyed2 = Arc::new(AtomicBool::new(false));
1578
1579 unsafe {
1580 let cpp_list = cpp_sll_create_unique_list();
1581 assert!(cpp_sll_unique_list_is_empty(cpp_list));
1582
1583 let obj1 = UniquePtr::try_new(SharedUniqueObject::new(1)).unwrap();
1584 let obj2 = UniquePtr::try_new(SharedUniqueObject::new(2)).unwrap();
1585
1586 let raw1 = UniquePtr::as_ptr(&obj1) as *mut SharedUniqueObject;
1588 (*raw1).destruction_flag = destroyed1.as_ptr() as *mut bool;
1589 let raw2 = UniquePtr::as_ptr(&obj2) as *mut SharedUniqueObject;
1590 (*raw2).destruction_flag = destroyed2.as_ptr() as *mut bool;
1591
1592 cpp_sll_unique_list_push_front(cpp_list, UniquePtr::into_raw(obj1) as *mut c_void);
1594 cpp_sll_unique_list_push_front(cpp_list, UniquePtr::into_raw(obj2) as *mut c_void);
1595
1596 assert!(!destroyed1.load(Ordering::Relaxed));
1597 assert!(!destroyed2.load(Ordering::Relaxed));
1598
1599 let popped = cpp_sll_unique_list_pop_front(cpp_list);
1601 assert!(!popped.is_null());
1602 assert_eq!(cpp_get_unique_object_value(popped), 2);
1603
1604 let popped_rust = UniquePtr::from_raw(popped as *mut SharedUniqueObject);
1606 drop(popped_rust);
1607 assert!(!destroyed1.load(Ordering::Relaxed));
1608 assert!(destroyed2.load(Ordering::Relaxed));
1609
1610 cpp_sll_destroy_unique_list(cpp_list);
1612 }
1613 assert!(destroyed1.load(Ordering::Relaxed));
1614 }
1615
1616 #[test]
1617 #[cfg_attr(miri, ignore = "miri does not support calling foreign functions")]
1618 fn test_interop_rust_list_cpp_ref_objects() {
1619 let destroyed1 = AtomicBool::new(false);
1620 let destroyed2 = AtomicBool::new(false);
1621
1622 unsafe {
1623 let mut list = SinglyLinkedList::<RefPtr<SharedRefObject>>::new();
1624
1625 let cpp_raw1 = cpp_create_ref_object(1, destroyed1.as_ptr() as *mut bool);
1626 let cpp_raw2 = cpp_create_ref_object(2, destroyed2.as_ptr() as *mut bool);
1627
1628 let obj1 = RefPtr::from_raw(cpp_raw1 as *mut SharedRefObject);
1629 let obj2 = RefPtr::from_raw(cpp_raw2 as *mut SharedRefObject);
1630
1631 list.push_front(obj1);
1632 list.push_front(obj2);
1633
1634 assert!(!destroyed1.load(Ordering::Relaxed));
1635 assert!(!destroyed2.load(Ordering::Relaxed));
1636
1637 let popped = list.pop_front();
1639 assert!(popped.is_some());
1640 assert_eq!(popped.as_ref().unwrap().value, 2);
1641
1642 drop(popped);
1644 assert!(!destroyed1.load(Ordering::Relaxed));
1645 assert!(destroyed2.load(Ordering::Relaxed));
1646
1647 }
1649 assert!(destroyed1.load(Ordering::Relaxed));
1650 }
1651
1652 #[test]
1653 #[cfg_attr(miri, ignore = "miri does not support calling foreign functions")]
1654 fn test_interop_cpp_list_rust_ref_objects() {
1655 let destroyed1 = Arc::new(AtomicBool::new(false));
1656 let destroyed2 = Arc::new(AtomicBool::new(false));
1657
1658 unsafe {
1659 let cpp_list = cpp_sll_create_ref_list();
1660 assert!(cpp_sll_ref_list_is_empty(cpp_list));
1661
1662 let obj1 = SharedRefObject::new_ref_counted(1);
1663 let obj2 = SharedRefObject::new_ref_counted(2);
1664
1665 let raw1 = RefPtr::as_ptr(&obj1) as *mut SharedRefObject;
1667 (*raw1).destruction_flag = destroyed1.as_ptr() as *mut bool;
1668 let raw2 = RefPtr::as_ptr(&obj2) as *mut SharedRefObject;
1669 (*raw2).destruction_flag = destroyed2.as_ptr() as *mut bool;
1670
1671 cpp_sll_ref_list_push_front(
1673 cpp_list,
1674 RefPtr::into_raw(obj1) as *mut SharedRefObject as *mut c_void,
1675 );
1676 cpp_sll_ref_list_push_front(
1677 cpp_list,
1678 RefPtr::into_raw(obj2) as *mut SharedRefObject as *mut c_void,
1679 );
1680
1681 assert!(!destroyed1.load(Ordering::Relaxed));
1682 assert!(!destroyed2.load(Ordering::Relaxed));
1683
1684 let popped = cpp_sll_ref_list_pop_front(cpp_list);
1686 assert!(!popped.is_null());
1687 assert_eq!(cpp_get_ref_object_value(popped), 2);
1688
1689 let popped_rust = RefPtr::from_raw(popped as *mut SharedRefObject);
1691 drop(popped_rust);
1692 assert!(!destroyed1.load(Ordering::Relaxed));
1693 assert!(destroyed2.load(Ordering::Relaxed));
1694
1695 cpp_sll_destroy_ref_list(cpp_list);
1697 }
1698 assert!(destroyed1.load(Ordering::Relaxed));
1699 }
1700}