Serde共享Arc序列化

3
我正在尝试使用Serde将共享引用保存到单个内存位置。我有一个小的结构体容器,其中包含两个类型为Arc<RwLock<f64>>的属性。我的目标是让这两个属性共享一个内存位置,以便当我改变一个属性时,另一个属性也会改变。当容器在主函数中创建时,这个方法可行。但是当我加载序列化的结构体ref0和ref1时,它们不再共享相同的内存位置,并且包含具有相同值的唯一内存位置。
是否可能向Serde指示ref0和ref1应该共享一个内存位置并且是“链接”的?
#[derive(Serialize, Deserialize)]
struct Container {
    pub(crate) ref0: Arc<RwLock<f64>>,
    pub(crate) ref1: Arc<RwLock<f64>>
}

保存场景(可行)

//makers ref0 and ref1, assign them to container.
let mut ref0 = Arc::new(RwLock::new(1.0));
let ref1 = ref0.clone();
let container = Container {
    ref0,
    ref1
};

// Checks that changing one ref will alter the other.
mem::replace(&mut *container.ref0.write().unwrap(), 2.0);
println!("{} {}",container.ref0.read().unwrap(), container.ref1.read().unwrap()); // should output "2.0 2.0" and does.
mem::replace(&mut *container.ref0.write().unwrap(), 3.0);
println!("{} {}",container.ref0.read().unwrap(), container.ref1.read().unwrap()); // should output "3.0 3.0" and does.

// Serializes the struct and save
let f_name = "SaveTest.test";
let mut file = File::create( f_name).unwrap();
let _result = file.write_all(&bincode::serialize(&container).unwrap());

加载场景(无法正常工作)

//LOAD THE CONTAINER
let mut buffer : Vec<u8> = vec![];
BufReader::new(File::open("SaveTest.test").unwrap()).read_to_end(&mut buffer).unwrap();
let container : Container = bincode::deserialize(&buffer).unwrap();

//Verifies that each ref is the same value when it was saved
println!("{} {}",container.ref0.read().unwrap(), container.ref1.read().unwrap()); // Should output "3.0 3.0" and does
mem::replace(&mut *container.ref0.write().unwrap(), 4.0);
println!("{} {}",container.ref0.read().unwrap(), container.ref1.read().unwrap()); // Should output "4.0 4.0" but outputs "4.0 3.0"

1
我认为这是不可能的。来自 https://serde.rs/feature-flags.html#-features-rc:“对这些类型进行序列化和反序列化不会保留身份,并且可能导致同一数据的多个副本。” - Chayim Friedman
1
通常情况下,序列化不是复制操作,也不能保留值的与内存相关的方面;它旨在绕过这些方面。 - Chayim Friedman
1个回答

1
无法使用Serde序列化引用。请参见如何使用Serde从读取器反序列化带有引用的结构体?。您可以创建一个自定义包装类型,将反序列化的Container值作为f64,然后在其中构建带有Arc-s的正确实例。
#[derive(Serialize, Deserialize)]
struct ContainerData {
    pub value: f64,
}

struct Container {
    pub(crate) ref0: Arc<RwLock<f64>>,
    pub(crate) ref1: Arc<RwLock<f64>>
}

impl Container {
    fn new(data: ContainerData) -> Self {
        let data_ref = Arc::new(data.value);
        Self {
            ref0: Arc::clone(&data_ref),
            ref1: Arc::clone(&data_ref),
        }
    }
}

根据您的评论,我理解需要创建两个结构体来保存相同的数据。其中一个结构体用于以有意义的方式存储引用,另一个则用于使用这些引用。 - Christian Potts
1
是的,将序列化代码与模型处理代码分开。 - battlmonstr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接