//! This is for testing the assumption that RootsWorkFactory can work with embedded Box or Arc //! to hold or share large components in the heap. Real-world RootsWorkFactory implementations //! should not be this complicated, and should probably not have shared mutable states, if they //! have any mutable states at all. use std::sync::{Arc, Mutex}; use mmtk::{ util::{Address, ObjectReference}, vm::RootsWorkFactory, }; #[derive(Default)] struct MockScanning { roots: Vec
, } impl MockScanning { fn add_roots(&mut self, roots: &[Address]) { self.roots.extend(roots); } fn mock_scan_roots(&self, mut factory: impl mmtk::vm::RootsWorkFactory
) { factory.create_process_roots_work(self.roots.clone()); } } static SLOTS: [Address; 3] = [ unsafe { Address::from_usize(0x8) }, unsafe { Address::from_usize(0x8) }, unsafe { Address::from_usize(0x8) }, ]; /// A factory with a plain value, a boxed value and a shared data with Arc. #[derive(Clone)] struct MockFactory { round: i32, v: String, #[allow(clippy::box_collection)] // for testing `Box` inside a factory b: Box, a: Arc>, } impl RootsWorkFactory
for MockFactory { fn create_process_roots_work(&mut self, slots: Vec
) { assert_eq!(slots, SLOTS); match self.round { 1 => { assert_eq!(self.v, "y"); assert_eq!(*self.b, "b"); assert_eq!(self.a.lock().unwrap().clone(), "a"); } 2 => { assert_eq!(self.v, "y"); assert_eq!(*self.b, "b"); assert_eq!(self.a.lock().unwrap().clone(), "a2"); } 3 => { assert_eq!(self.v, "y2"); assert_eq!(*self.b, "b2"); assert_eq!(self.a.lock().unwrap().clone(), "a2"); } _ => { panic!("Unreachable"); } } } fn create_process_pinning_roots_work(&mut self, _nodes: Vec) { unimplemented!(); } fn create_process_tpinning_roots_work(&mut self, _nodes: Vec) { unimplemented!(); } } #[test] fn test_scan() { let factory = MockFactory { round: 1, v: "y".to_string(), b: Box::new("b".to_string()), a: Arc::new(Mutex::new("a".to_string())), }; let mut scanning = MockScanning::default(); scanning.add_roots(&SLOTS); scanning.mock_scan_roots(factory); } #[test] fn test_clone() { let factory1 = MockFactory { round: 2, v: "y".to_string(), b: Box::new("b".to_string()), a: Arc::new(Mutex::new("a".to_string())), }; let mut factory2 = factory1.clone(); factory2.round = 3; factory2.v = "y2".to_string(); *factory2.b = "b2".to_string(); *factory2.a.lock().unwrap() = "a2".to_string(); let mut scanning = MockScanning::default(); scanning.add_roots(&SLOTS); scanning.mock_scan_roots(factory1); scanning.mock_scan_roots(factory2); }