【发布时间】:2021-05-26 00:27:10
【问题描述】:
假设我有一个用户空间 TCP/IP 堆栈。我很自然地将它包装在Arc<Mutex<>> 中,以便与我的线程分享。
我想为它实现AsyncRead 和AsyncWrite 也是很自然的,所以像hyper 这样期望impl AsyncWrite 和impl AsyncRead 的库可以使用它。
这是一个例子:
use core::task::Context;
use std::pin::Pin;
use std::sync::Arc;
use core::task::Poll;
use tokio::io::{AsyncRead, AsyncWrite};
struct IpStack{}
impl IpStack {
pub fn send(self, data: &[u8]) {
}
//TODO: async or not?
pub fn receive<F>(self, f: F)
where F: Fn(Option<&[u8]>){
}
}
pub struct Socket {
stack: Arc<futures::lock::Mutex<IpStack>>,
}
impl AsyncRead for Socket {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>
) -> Poll<std::io::Result<()>> {
//How should I lock and call IpStack::read here?
Poll::Ready(Ok(()))
}
}
impl AsyncWrite for Socket {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<Result<usize, std::io::Error>> {
//How should I lock and call IpStack::send here?
Poll::Ready(Ok(buf.len()))
}
//poll_flush and poll_shutdown...
}
我认为我的假设没有任何问题,也没有其他更好的方法来与多个线程共享堆栈,除非我将其包装在 Arc<Mutex<>>
这类似于引起我兴趣的try_lock on futures::lock::Mutex outside of async?。
我应该如何在不阻塞的情况下锁定互斥锁?请注意,一旦我获得锁,IpStack 就不是异步的,它调用了该块。我也想对其实现异步,但我不知道问题会变得更加困难。或者如果它有异步调用,问题会变得更简单吗?
【问题讨论】:
标签: multithreading rust concurrency mutex