Reputation: 2148
Suppose I have an object video_source: Option<Arc<Mutex<Box<dyn GetVideo>>>>
and I pass it to a thread:
std::thread::spawn(||{
loop {
if let Some(video_source) = video_source {
let video_frame = video_source.lock().unwrap().get();
}
}
})
where
trait GetVideo {
fn get() -> Vec<u8>
}
What if I want to change the video source on the fly? Well, I'd do this on another thread:
video_frame.unwrap().lock().unwrap() = Box::new(other_source);
I want to make this idea more generic. I want a type that permits such thing. Here's my sketch:
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();
}
}
However, I cannot make something generic over T
where T
is a trait, it should be a type.
Any ideas?
This is solved by @user4815162342. But what if I want to make one OnTheFly
object point to the same thing as the other one?
Upvotes: 0
Views: 832
Reputation: 60052
First, you are correct that T
cannnot be a trait like GetVideo
; traits are not types. However, T
can be dyn GetVideo
.
Second, your aliases have generic parameters, so they should be reflected as such in the function signature:
pub fn on_the_fly_substitute<T>(on_the_fly: &mut Option<OnTheFly<T>>, substitute_by: Option<OnTheFlyInner<T>>)
^^^ ^^^ ^^^
Third, your alias looks like an attempt to constrain T
to be Send
+ Sync
, but aliases cannot define additional bounds. You would instead put them on the function (with ?Sized
since you want to allow trait objects):
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
{
...
}
Note: your function body does not require Send
and Sync
so these bounds should probably not be included.
Fourth, Option<Arc<Mutex<Box<dyn GetVideo>>>>
is not thread safe. You'll need to constrain that the trait object is at least Send
:
Option<Arc<Mutex<Box<dyn GetVideo + Send>>>>
^^^^^^
Fifth, a complete example is lacking, but you appear to be wanting multiple threads to modify the same video_source
. This would likely not compile since you would need multiple threads to keep a &mut _
in order to change it.
If you want shared ownership of a value that might not exist, move the option into the Mutex
and adjust your function and aliases accordingly:
video_source: Arc<Mutex<Option<Box<dyn GetVideo>>>>
Sixth, your comment "I'd like this to be a method of OnTheFly
" is misguided. Aliases are just aliases, you'd need a method on the aliased Option
/Arc
type. Keep it as a free function, introduce an extension trait for it, or create it as a wrapper type instead of an alias if you want more fine-grained control.
Upvotes: 5