Just curious if I can resume
a generator from multi threads. If so how to pass generator to multi threads?
This depends on whether the generator's internal state is thread-safe. For example, this generator which captures an Arc
can be sent to another thread:
let mut arc = Arc::new(true);
let mut generator0 = move || {
yield arc.clone()
};
spawn(move || Pin::new(&mut generator0).resume(()));
But if we change the Arc
to Rc
:
let mut rc = Rc::new(true);
let mut generator1 = move || {
yield rc.clone()
};
spawn(move || Pin::new(&mut generator1).resume(()));
then we get this compiler error:
error[E0277]: `Rc<bool>` cannot be sent between threads safely
--> src/main.rs:24:11
|
24 | spawn(move || Pin::new(&mut generator1).resume(()));
| ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Rc<bool>` cannot be sent between threads safely
| |
| required by a bound introduced by this call
|
= help: within `GeneratorState<Rc<bool>, ()>`, the trait `Send` is not implemented for `Rc<bool>`
= note: required because it appears within the type `GeneratorState<Rc<bool>, ()>`
note: required by a bound in `spawn`
Following code is my try , the program panic at line A because of multi references on the Arc
. So what is the right way?
fn generator() {
let mut x = || {
let mut sum = 0;
for i in 1..=10 {
sum+=i;
yield i;
}
sum
};
let mut arc = Arc::new(x);
let mut t = vec![];
for i in 1..=3 {
let mut x = arc.clone();
let y = move|| {
let mut x = Arc::get_mut(&mut x).unwrap(); // A
loop {
match Pin::new(&mut x).resume(()) {
GeneratorState::Yielded(x) => println!("yield {}",x),
GeneratorState::Complete(x) => {
println!("complete {}",x);
break;
}
}
}
};
t.push(thread::spawn(y));
}
for i in t {
i.join();
}
}
Arc::get_mut
is rarely useful; it can only be used while the Arc
has no clones.
If you want to mutate a value while it is shared across threads, you'll need to protect it with some sort of synchronization, like a Mutex
:
let arc = Arc::new(Mutex::new(x));
and then .lock()
the mutex when you need to mutate its contents:
match Pin::new(&mut *x.lock().unwrap()).resume(()) {
See this playground for a complete example.
thank you. got it.
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.