即时替换`Option<Arc<Mutex<Box<dynT>>>>`

假设我有一个对象video_source: Option<Arc<Mutex<Box<dyn GetVideo>>>>并将它传递给一个线程:

std::thread::spawn(||{
    loop {
        if let Some(video_source) = video_source {
            let video_frame = video_source.lock().unwrap().get();
        }
    }
})

在哪里

trait GetVideo {
    fn get() -> Vec<u8>
}

如果我想即时更改视频源怎么办?好吧,我会在另一个线程上这样做:

video_frame.unwrap().lock().unwrap() = Box::new(other_source);

我想让这个想法更通用。我想要一种允许这种事情的类型。这是我的草图:

use std::sync::{Arc, Mutex};

pub type OnTheFlyInner<T> = Box<T + Send + Sync>;
pub type OnTheFly<T> = Arc<Mutex<OnTheFlyInner<T>>>;

//I'd like this to be a method of `OnTheFly`
pub fn on_the_fly_substitute(on_the_fly: &mut Option<OnTheFly>, substitute_by: Option<OnTheFlyInner>) {
    if let Some(substitute_by) = substitute_by {
        if let Some(on_the_fly) = on_the_fly {
            *on_the_fly.lock().unwrap() = substitute_by;
        }
    } else {
        on_the_fly.take();
    }
}

但是,我不能对特征的T位置进行通用化T,它应该是一种类型。

有任何想法吗?


赏金

这是由@user4815162342 解决的。但是如果我想让一个OnTheFly对象和另一个对象指向同一个对象呢?

回答

首先,你是正确的,T不能成为像GetVideo; 特质不是类型。不过,T可以dyn GetVideo

其次,您的别名具有通用参数,因此它们应该在函数签名中反映出来:

pub fn on_the_fly_substitute<T>(on_the_fly: &mut Option<OnTheFly<T>>, substitute_by: Option<OnTheFlyInner<T>>)
                            ^^^                                 ^^^                                      ^^^

第三,您的别名看起来像是试图将其限制 TSend+ Sync,但别名无法定义其他边界。您可以将它们放在函数上(?Sized因为您希望允许 trait 对象):

pub fn on_the_fly_substitute<T: ?Sized>(on_the_fly: &mut Option<OnTheFly<T>>, substitute_by: Option<OnTheFlyInner<T>>)
where
    T: ?Sized + Send + Sync
{
    ...
}

注意:您的函数体不需要SendSync因此可能不应该包含这些边界。

第四,Option<Arc<Mutex<Box<dyn GetVideo>>>>不是线程安全的。您需要限制 trait 对象至少是Send

Option<Arc<Mutex<Box<dyn GetVideo + Send>>>>
                                  ^^^^^^

第五,缺少完整的示例,但您似乎希望多个线程修改相同的video_source. 这可能无法编译,因为您需要多个线程来保留 a&mut _才能更改它。

如果您想要共享一个可能不存在的值的所有权,请将选项移动到Mutex并相应地调整您的函数和别名:

video_source: Arc<Mutex<Option<Box<dyn GetVideo>>>>

第六,您的评论“我希望这是一种方法OnTheFly是错误的。别名只是别名,您需要一个别名Option/Arc类型的方法。保持它作为一个自由函数,为它引入一个扩展特性,或者如果你想要更细粒度的控制,或者将它创建为包装类型而不是别名。


以上是即时替换`Option&lt;Arc&lt;Mutex&lt;Box&lt;dynT&gt;&gt;&gt;&gt;`的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>