如何在Rust中跨多个结构创建连续内存池?

如何在Rust中跨多个结构创建连续内存池?,rust,Rust,我正在尝试在Rust中创建一组使用连续内存块的结构。例如: <------------ Memory Pool --------------> [ Child | Child | Child | Child ] [孩子|孩子|孩子|孩子] 这些结构: 每个可以包含不同大小的池片 初始化后,应该允许访问池中的片段,而无需任何阻塞操作(我打算通过音频线程访问它们) 我很生锈,但我精通C++,所以目前的主要障碍是使用所有权语义——我猜有一个很小的方法来实现这个(不

我正在尝试在Rust中创建一组使用连续内存块的结构。例如:

<------------ Memory Pool -------------->
[  Child  |  Child  |  Child  |  Child  ]

[孩子|孩子|孩子|孩子]
这些结构:

  • 每个可以包含不同大小的池片

  • 初始化后,应该允许访问池中的片段,而无需任何阻塞操作(我打算通过音频线程访问它们)

<>我很生锈,但我精通C++,所以目前的主要障碍是使用所有权语义——我猜有一个很小的方法来实现这个(不使用不安全的),但解决办法我不清楚。我写了一个小的(不完整的)例子来说明我要做的事情:

pub struct Child<'a> {
    pub slice: &'a mut [f32],
}

impl Child<'_> {
    pub fn new<'a>(s: &mut [f32]) -> Child {
        Child {
            slice: s,
        }
    }
}

pub struct Parent<'a> {
    memory_pool: Vec<f32>,
    children: Vec<Child<'a>>,
}

impl Parent<'_> {
    pub fn new<'a>() -> Parent<'a> {
        const SIZE: usize = 100;
        let p = vec![0f32; SIZE];
        let mut p = Parent {
            memory_pool: p,
            children: Vec::new(),
        };
        // Two children using different parts of the memory pool:
        let (lower_pool, upper_pool) = p.memory_pool.split_at_mut(SIZE / 2);
        p.children = vec!{ Child::new(lower_pool), Child::new(upper_pool) };
        return p; // ERROR - p.memory_pool is borrowed 2 lines earlier
    }
}
pub-struct-Child(s:&mut[f32])->Child{
孩子{
切片:s,
}
}
}
发布结构父级>,
}

impl Parent()->Parent是的,在Rust中,目前不可能(或很难)将引用包含到同级数据中,例如,正如您在这里看到的,一个
Vec
并将其作为同一
struct
中的字段切片到该
Vec
。根据程序的体系结构,您可以通过将原始
Vec
存储在代码的某个更高级别来解决此问题(例如,如果您没有编写库,它可能位于
main()
中的堆栈上)并且切片引用在某个较低的级别,编译器可以清楚地推断它在
Vec
之前不会超出范围(例如,在
Vec
实例化之后在
main()
中执行它可以工作)。

这是arena分配器的完美用例。有很多。以下演示使用:

/#bumpalo=“2.6.0”
使用bumpalo::Bump;
使用std::mem::size\u;
结构Child1(u32,u32);
结构Child2(f32,f32,f32);
fn main(){
让arena=Bump::new();
设c1=arena.alloc(Child1(1,2));
设c2=arena.alloc(Child2(1.0,2.0,3.0));
设c3=arena.alloc(Child1(10,11));
//让我们验证它们在内存中是否确实是连续的
设ptr1=c1为*mut_uu为usize;
设ptr2=c2为*mut_uu为usize;
设ptr3=c3为*mut_uu为usize;
断言(ptr1+大小::(),ptr2);
断言(ptr1+size\u of::()+size\u of::(),ptr3);
}
还有一些警告。主要关注的当然是,;两个连续的分配之间可能存在一些填充。如果这是一个交易破坏者,你应该确保这不会发生

另一个是特定于分配器的。例如,这里使用的bumpaloarena分配器在对象本身被释放时不会
删除
对象


除此之外,我相信这样一个更高级别的抽象将对您的项目有益。否则,它将只是伪装成锈迹的指针操作c/c++。

您好!我想你的问题已经有答案了。不过我并没有马上结束你的问题,因为也许你可以绕过这个限制。您的
f32
向量何时更改?你是否考虑过如果它重新定位会发生什么?你将如何在C++中完成这个任务?不能在结构中引用引用,C++标准没有“<代码>限制< /代码> /<代码>和MUT<代码>,所以<代码>子< /代码>根本不翻译。你会使用原始指针吗?这是锈病中不安全的解决方案。或者你会使用索引吗?您可以在锈迹斑斑的环境中进行此操作,而无需
不安全的
。您将如何处理底层
std::vector
的重新分配?无论你的解决方案是什么,在C++中,我几乎可以保证你可以在锈中做同样的事情。但是,如果您正在使用特定于生锈的工具,如生命周期和
&mut
,您将无法复制它。