代码之家  ›  专栏  ›  技术社区  ›  dflemstr

自有竞技场数据结构[副本]

  •  0
  • dflemstr  · 技术社区  · 8 年前

    我想建模一个非常大(节点数)的图,它由许多非常大(内存)的节点组成。由于节点太大,我只想存储一次,并将借方传递给它们,因此在概念上是这样的:

    struct Graph<'a> {
        nodes: Vec<Node<'a>>,
    }
    
    struct Node<'a> {
        edges: HashMap<String, &'a Node>,
        // ...lots of other data...
    }
    

    当然,没有办法构造 Graph 这样做是因为(a) Vec 不允许我在元素有借用时添加新节点,并且(b)我不能告诉rustc nodes 矢量将终生存在 'a 。我也不能使用类似 Rc 因为该图具有循环。

    我想表达的是一个各种各样的竞技场,它让我分配了很多 Node s、 只要竞技场还活着,就向他们借不可变的钱,并使用终身检查来确保我没有剩余的钱 节点 竞技场取消分配时的参考。类似于:

    struct Graph<'a> {
        nodes: Arena<'a, Node<'a>>,
    }
    
    struct Node<'a> {
        edges: HashMap<String, &'a Node>,
    }
    
    impl<'a, A> Arena<'a, A> {
        fn own(&self, a: A) -> &'a A {
            // magic
        }
    }
    
    impl<'a, A> Drop for Arena<'a, A> {
        fn drop(&'a mut self) {
            // magic
        }
    }
    

    这在语义上可以用Rust表达吗?

    1 回复  |  直到 8 年前
        1
  •  3
  •   Matthieu M.    8 年前

    一个简单的解决方案是使用 typed-arena 大木箱它包含一个 Arena 键入 fn alloc(&self, T) -> &mut T 方法

    另一个简单的解决方案是使用索引而不是引用(并且永远不要从 Vec 因为这将使索引无效)。在64位平台上,使用32位索引可以减少一些字节。

    然而,这两种解决方案都无法 去除 节点。您可以停止引用它们,但它们仍将存在于内存中,因此,将它们用于动态图(节点来去)需要更多的工作。在这种情况下,我的建议是定期从新的竞技场创建一个新的图形克隆(不要复制未使用的节点),这类似于使用移动垃圾收集器(如果不是自动的话)。