创建两个可变引用,这些引用对Rust中的结构是线程安全的

问题描述 投票:0回答:1

我正在尝试在tokio中创建异步Reader和Writer,这些需要Send,并且必须是线程安全的。 (似乎不是编写避免多文本的单线程tokio代码的方法)

读取器和写入器都需要交互,例如读取数据可能会导致响应。

我希望Reader和Writer都具有指向Session的线程安全指针,以确保两者之间的通信。

/// function on the 
impl Session {

pub fn split(&mut self, sock: TcpStream) -> (Reader, Writer) {
    let (read_half, write_half) = sock.split();

    let session = Arc::new(RwLock::new(self)); // <- expected lifetime

    ( Reader::new(session, read_half), Writer::new(Arc::clone(session), write_half) )
}
...
}

pub struct Reader {
    session: Arc<RwLock<&mut StompSession>>,
    read_half: ReadHalf<TcpStream>,
    ...

pub struct Writer {
    session: Arc<RwLock<&mut StompSession>>,
    write_half: WriteHalf<TcpStream>,
    ....

我不太了解Arc<RwLock<&mut StompSession>>Arc<RwLock<StompSession>>之间的区别,它们都只能谈论指针。

[通过自然地使用借阅检查器来解决这个问题,生锈的书只提供了带有整数而不是可变的“对象”的RRwLock的示例。

multithreading rust automatic-ref-counting mutex mut
1个回答
1
投票

让我们先清除一些内容:

似乎不是编写避免互斥的单线程tokio代码的方法

Mutex要求与单线程无关,但与可变借位无关。每当您产生一个未来时,那个未来就是它自己的实体。它不是struct的魔术部分,大多数definitely不知道如何保存&mut self。这就是Mutex的意义-它允许您动态获取对内部状态的可变引用-并且Arc允许您在多个位置访问Mutex本身。

顺便说一下,[它们的非同步等效项是RcCell / RefCell,并且它们的内容(无论是同步的还是未同步的)应该是拥有的类型。

Send要求实际上是在futures上方使用tokio时显示的,因为Executor要求在其上产生的期货为Executor(出于明显的原因-您could Send方法,但这会导致超出解决方案的更多问题)。

现在,回到您的问题。我将为您提供最短路径来解答您的问题。但是,这将不是完全正确的处理方式。但是,由于我不知道您要在spawn_local之上使用什么协议或您有什么样的要求,因此我无法指出正确的方向(尚未)。因此,这里有评论-给我更多的要求,我会很乐意对此进行编辑!

反正回到问题。由于TcpStream更适合用于自有类型,因此我们现在要这样做,并“修复”您的Mutex<_>Reader

Writer

由于我们已对此进行了更改,因此我们还需要在其他地方进行反映,但是要做到这一点,我们将需要消耗pub struct Reader { session: Arc<RwLock<Session>>, read_half: ReadHalf<TcpStream>, } pub struct Writer { session: Arc<RwLock<StompSession>>, write_half: WriteHalf<TcpStream>, } 。很好,但是,由于我们将在两个对象中都有一个self副本,因此我们返回:

Arc<Mutex<_>>

然后瞧瞧,它会编译,并且每个impl Session { pub fn split(self, sock: TcpStream) -> (Reader, Writer) { let (read_half, write_half) = sock.split(); let session = Arc::new(RwLock::new(self)); ( Reader::new(session.clone(), read_half), Writer::new(session, write_half) ) } } / Writer对现在都有自己的可借用(可变和非可变)引用我们的会话!

Reader高亮显示所做的更改。就像我说的那样,它现在可以工作,但是当您尝试做某事时,它会被您咬死,因为您需要在playground snippetReadHalf上都需要一些东西才能正确使用它们。

© www.soinside.com 2019 - 2024. All rights reserved.