Reputation: 1693
In this code snippet (playground link), we have some simple communication between two threads. The main thread (which executes the second async
block) sends 2
to thread 2 in the async move
block, which receives it, adds its own value, and sends the result back over another channel to the main thread, which prints the value.
Thread 2 contains some local state, the thread_unsafe
variable, which is neither Send
nor Sync
, and is maintained across an .await
. Therefore the impl Future
object that we are creating is itself neither Send
nor Sync
, and hence the call to pool.spawn_ok
is a compile error.
However, this seems like it should be fine. I understand why spawn_ok()
can't accept a future that is not Send
, and I also understand why the compilation of the async block into a state machine results in a struct that contains a non-Send
value, but in this example the only thing I want to send to the other thread is recv
and send2
. How do I express that the future should switch to non-thread safe mode only after it has been sent?
use std::rc::Rc;
use std::cell::RefCell;
use futures::channel::oneshot::channel;
use futures::executor::{ThreadPool, block_on};
fn main() {
let pool = ThreadPool::new().unwrap();
let (send, recv) = channel();
let (send2, recv2) = channel();
pool.spawn_ok(async move {
let thread_unsafe = Rc::new(RefCell::new(40));
let a = recv.await.unwrap();
send2.send(a + *thread_unsafe.borrow()).unwrap();
});
let r = block_on(async {
send.send(2).unwrap();
recv2.await.unwrap()
});
println!("the answer is {}", r)
}
Upvotes: 1
Views: 340
Reputation: 155216
but in this example the only thing I want to send to the other thread is
recv
andsend2
There is also the local variable thread_unsafe
which is used across an .await
. Since .await
can suspend an async function, and later resume it on another thread, this could send thread_unsafe
to a different thread, which is not allowed.
Upvotes: 2