如何在启用价值突变的同时允许多个所有者?

How can I allow multiple owners while enabeling mutation of value?

我有一个 Enum,叫做 NodeType 允许 Network(Network)Mesh(Mesh)[=59= 的值]。 Network和Mesh都是未知大小的结构体。网络实例包含节点结构的二维矢量,其中包含节点类型枚举,允许网络包含其他网络或网格结构。网格执行一些任意功能。

考虑以下 Network,它的 NodeType 向量大小为 1 x 3。内容为:[Mesh, Network0, Network1]first 元素(Mesh),做了一些事情并且无关紧要。 Second 元素 Network0 已创建,并在实例化时分配了一个 NodeType(Mesh)。与先前的包含 Mesh 的 Network 一样,这无关紧要。

第三个 元素 Network1 的创建方式与 Network0 相同,在创建时定义了 NodeType(Mesh)。但是,我们现在要向 Network1 的 NodeType Vector 添加一个新值。我的问题是我在为递归结构而不是递归循环的“根”分配值时遇到问题。在任何给定时间,一个子网络可能被多个父网络引用。我无法执行这些 NodeType 的深层复制,因为它可能(无限)大。

我看到的问题是节点包含 Arc。但是这些都是需要的,因为 Arc 允许很多 Networks 引用同一个 Struct 实例,而 RwLock 允许在线程时进行管理。

以下是使用的三个结构,以及实例化上述场景的主要结构:

节点

#[derive(Debug)]
pub(crate) struct Node {
    guid: Uuid,
    node: Arc<RwLock<NodeType>>,
}

impl Node {
    pub(crate) fn new(subnet: NodeType) -> Node {
        Node {
            guid: Uuid::new_v4(),
            node: Arc::new(RwLock::new(subnet))
        }
    }

    pub(crate) fn node(self) -> Arc<RwLock<NodeType>> {
        self.node.clone()
    }
}

#[derive(Debug)]
pub(crate) enum NodeType {
    Network(Network),
    Mesh(Mesh),
}

网络

#[derive(Debug)]
pub(crate) struct Network {
    guid: Uuid,
    pub(crate) subnet: Vec<Vec<Node>>,
}

impl Network {
    pub(crate) fn new(subnet: NodeType) -> Network {
        Network {
            guid: Uuid::new_v4(),
            subnet: vec![vec![Node::new(subnet)]],
        }
    }
}

网格

#[derive(Debug, )]
pub(crate) struct Mesh {
    guid: Uuid,
}

impl Mesh {
    pub(crate) fn new() -> Mesh {
        Mesh {
            guid: Uuid::new_v4(),
        }
    }
}

主要

    //Creates A NodeType(Mesh)
    let a = NodeType::Mesh(Mesh::new());
    //Assigns the NodeType(Mesh) as the Second Element
    let mut agent0 = Network::new(a);

    //Creates a NodeType(Network) that Contains a Single Mesh
    let b = NodeType::Network(Network::new(NodeType::Mesh(Mesh::new())));
    //Assigns A NodeType(Network) that Contains a NodeType(Mesh) as the first element.
    agent0.subnet[0].push(Node::new(b));

    //Creates a NodeType(Network), Containing A NodeType(Mesh)
    let c = NodeType::Network(Network::new(NodeType::Mesh(Mesh::new())));
    //Assigns A NodeType(Network) that Contains a NodeType(Mesh) as the third element.
    agent0.subnet[0].push(Node::new(c));

    //An Attempt to append an additional Mesh to the Third Element's NodeType Vector. (Not Currently Working)
    let value = (*agent0.subnet[0][2].node()).get_mut();
    if let NodeType::Network(mut content) = value {
        // let d = NodeType::Mesh(Mesh::new());
        // content.subnet[0].push(Arc::new(RwLock::new(NodeType::Mesh(Mesh::new()))))
    }

收到的错误是:

let i = (*agent0.subnet[0][2].node()).get_mut();
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable

trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Arc<async_std::sync::RwLock<NodeType>>`

我希望我的问题很清楚,我决定冒过度解释的风险而不是替代方案。

我认为这里的问题是你有一个 Arc<RwLock<NodeType>> 但当你只有一个不可变的引用时你试图 get_mut() 。正如 the documentation for RwLock 所说,

use std::sync::RwLock;

let lock = RwLock::new(5);

// many reader locks can be held at once
{
    let r1 = lock.read().unwrap();
    let r2 = lock.read().unwrap();
    assert_eq!(*r1, 5);
    assert_eq!(*r2, 5);
} // read locks are dropped at this point

// only one write lock may be held, however
{
    let mut w = lock.write().unwrap();
    *w += 1;
    assert_eq!(*w, 6);
} // write lock is dropped here

所以你的代码缺少的是 Arc 只给你一个 non-mutable 引用你的 RwLock 这意味着你需要调用write ,然后 unrwap() 因为可能的结果,按照上面的示例获取对内部 NodeType.

的可变引用

编辑:我认为这就是您在最后一节中想要的内容。虽然不能 100% 确定,因为它不会克隆您的 Arc,但我认为这就是您 尝试 要做的事情:

    //An Attempt to append an additional Mesh to the Third Element's NodeType Vector.
    let mynode = &(agent0.subnet[0][2]);
    let mut locker = mynode.node.write().unwrap();
    if let NodeType::Network(content) = &mut *locker {
        let my_mesh_nodetype = NodeType::Mesh(Mesh::new());
        let my_fresh_node = Node::new(my_mesh_nodetype);
        content.subnet[0].push(my_fresh_node);
    }

根据您在代码中的评论,我认为这是正确的。