I have the problem of polling an Arc. As you see, the Arc is actually transfered to C. I do not use it anywhere after it is transfered to C. Since C must be Sync+Send, I cannot use a more simple container, so I use Arc:
use std::sync::Arc;
use core::task::{Context, Poll};
use std::pin::Pin;
use tokio::io::{AsyncRead};
trait A{
}
impl AsyncRead for A {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>
) -> Poll<std::io::Result<()>> {
Poll::Ready(Ok(()))
}
}
pub struct C{
c: Arc<dyn A + Send + Sync >
}
impl C {
//Here we actually transfer/move our Arc<dyn A + Send + Sync >,
//we don't use it anymore on the other thread
pub fn new(c: Arc<dyn A + Send + Sync >) -> C {
C {
c: c
}
}
}
impl AsyncRead for C {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>
) -> Poll<std::io::Result<()>> {
//since `c` is `Arc`, it has no interior mutability, so I cannot call `poll_read` on it
self.c.poll_read(cx, buf)
}
}
however, by using Arc I cannot do self.c.poll_read(cx, buf) because Arc does not provide interior mutability. In this case, however, I use Arc not for sharing between threads, but actually for sending C to other threads. If I simply did Arc<Mutex<dyn A + Send + Sync>> then it would work and I could poll with self.c.lock().unwrap()poll_read(cx, buf). Since C is the only owner, it would block immediately, so no problem using inside poll_read, but is there a more elegant way of solving this problem?
Is there a type that can be sent to other threads in such a way that it is moved to that thread in such a way that it preserves interior mutability so I can poll it?
maybe? But I'd have to lock it at every call, wouldn't I? Not that this is a problem since there's only one owner, but isn't there something better than a Mutex? Something with Interior mutability + Send, without lock
Well, RefCell<T> is Send iff T: Send and it has interior mutability. If your inner type is not Send, then I don't see how you could make it so without locking.
I'm trying with Mutex just to see what happens but I get
error[E0599]: no method named `poll_read` found for struct `std::sync::MutexGuard<'_, (dyn AsyncRW + Sync + std::marker::Send + 'static)>` in the current scope
--> src/async_transporter.rs:80:37
|
80 | self.stream.lock().unwrap().poll_read(cx, buf)
| ^^^^^^^^^ method not found in `std::sync::MutexGuard<'_, (dyn AsyncRW + Sync + std::marker::Send + 'static)>`
which made me wonder. How do I know if I can call poll_read through MutexGuard? I looked at MutexGuard in std::sync - Rust but couldn't find anything.
Also, is the error above possibly happening because I should pin things? How can I pin the result of the mutex lock?
I think self.lock.data.get() gets a pointer to the data. * before it acesses the value, and &mut returns a reference. So dereferencing returns a reference to the inner type T?
Also, doesn't *self.lock.data.get() create a copy? Or &mut before it means "address of object at *self.lock().data.get()"?
error[E0277]: the size for values of type `dyn AsyncRW + Sync + std::marker::Send` cannot be known at compilation time
--> src/async_transporter.rs:105:9
|
105 | Pin::new(*self.stream.lock().unwrap()).poll_shutdown(cx)
| ^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `dyn AsyncRW + Sync + std::marker::Send`
= note: all function arguments must have a statically known size