假设我有一个包装矢量的“图像”结构:
type Color = [f64; 3];
pub struct RawImage
{
data: Vec<Color>,
width: u32,
height: u32,
}
impl RawImage
{
pub fn new(width: u32, height: u32) -> Self
{
Self {
data: vec![[0.0, 0.0, 0.0]; (width * height) as usize],
width: width,
height: height
}
}
fn xy2index(&self, x: u32, y: u32) -> usize
{
(y * self.width + x) as usize
}
}
它可以通过“视图”结构访问,该结构抽象了图像的内部块。假设我只想写入图像 ( set_pixel()
)。
pub struct RawImageView<'a>
{
img: &'a mut RawImage,
offset_x: u32,
offset_y: u32,
width: u32,
height: u32,
}
impl<'a> RawImageView<'a>
{
pub fn new(img: &'a mut RawImage, x0: u32, y0: u32, width: u32, height: u32) -> Self
{
Self{ img: img,
offset_x: x0, offset_y: y0,
width: width, height: height, }
}
pub fn set_pixel(&mut self, x: u32, y: u32, color: Color)
{
let index = self.img.xy2index(x + self.offset_x, y + self.offset_y);
self.img.data[index] = color;
}
}
现在假设我有一个图像,我希望有 2 个线程同时修改它。这里我使用了 rayon 的作用域线程池:
fn modify(img: &mut RawImageView)
{
// Do some heavy calculation and write to the image.
img.set_pixel(0, 0, [0.1, 0.2, 0.3]);
}
fn main()
{
let mut img = RawImage::new(20, 10);
let pool = rayon::ThreadPoolBuilder::new().num_threads(2).build().unwrap();
pool.scope(|s| {
let mut v1 = RawImageView::new(&mut img, 0, 0, 10, 10);
let mut v2 = RawImageView::new(&mut img, 10, 0, 10, 10);
s.spawn(|_| {
modify(&mut v1);
});
s.spawn(|_| {
modify(&mut v2);
});
});
}
这不起作用,因为
- 我
&mut img
同时有2个,这是不允许的 - “闭包的寿命可能比当前函数长,但它借用
v1
了当前函数所拥有的 ”
所以我的问题是
- 如何修改
RawImageView
,以便我可以有 2 个线程修改我的图像? - 即使线程是作用域的,为什么它仍然抱怨闭包的生命周期?我该如何克服呢?
我尝试过的一种方法(并且有效)是modify()
创建并返回 a RawImage
,然后让线程将其推送到向量中。完成所有线程后,我从该向量构造了完整图像。由于它的 RAM 使用率,我试图避免这种方法。