如何使RAII性能的用户对象?

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

我在用怎样的一个发布/订阅模式的链接交谈一些硬件。在C ++中,我与RAII订阅记得要随时取消订阅,但我似乎无法获得所有权/借用权生锈。

天真,这是一样的东西,我想做些什么。 sendreceive可能必须&mut self,所以按照我的理解,Subscription需要的Transport可变访问。

struct Transport;

impl Transport {
    pub fn send(&mut self, cmd: &str) { unimplemented!() }
    pub fn subscribe(&mut self, cmd: &str) -> Subscription {
        self.send("subscribe-with-params");
        Subscription { trans: &mut self }
    }
}

struct Subscription {
    trans: &mut Transport,
}

impl Drop for Subscription {
    fn drop(&mut self) {
        self.trans.send("unsubscribe-with params");
    }
}

impl Subscription {
    fn receive(&mut self) -> &[u8] { /*blocking wait for data*/ }
}

fn test(t: Transport) {
    // Need to subscribe before command, as command might generate status messages
    let mut status_sub = t.subscribe("status-message");
    {
        let mut short_lived_sub = t.subscribe("command_reply");
        t.send("command");
        short_lived_sub.receive(); // Wait for ack
    }
    loop {
        println!("{:?}", status_sub.receive());
        /*processing of status */
    }
}

这里有至少两个问题。一是Subscription应该如何保持一定的参考它的“父母”,在Transport,另一种是在fn test,我不能借Transport两次,两个不同的订阅问题。

我有一种感觉,我是那种问错了问题在这里,也许有一个在完全不同的方式处理这个的一个好办法吗?

rust raii borrow-checker interior-mutability
1个回答
2
投票

这是有问题的为您Subscription举行可变引用Transport因为,当你发现,你只能将能够容纳一次一个,你将无法做任何事,在此期间的运输。

相反,你可以使用Rc(共享所有权)和RefCell(室内可变性):

use std::rc::Rc;
use std::cell::RefCell;

struct TransportInner;

pub struct Transport {
    inner: Rc<RefCell<TransportInner>>,
}

pub struct Subscription { 
    trans: Rc<RefCell<TransportInner>>
}

impl TransportInner {
   pub fn send(&mut self, cmd: &str) { }
}

impl Transport {
   pub fn send(&mut self, cmd: &str) { 
       self.inner.borrow_mut().send(cmd)
   }

   pub fn subscribe(&mut self, cmd: &str) -> Subscription {
      self.send("subscribe-with-params");
      Subscription { trans: Rc::clone(&self.inner) }
   }
}

impl Drop for Subscription {
   fn drop(&mut self) {
      self.trans.borrow_mut().send("unsubscribe-with params");
   }
}

你可以做到这一点,不要把它变成一个内部和外部的结构,但这需要用户通过Transport过,这可能是笨拙的访问Rc

如果你需要这个跨线程工作,你应该使用Arc<Mutex>

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