rust - C++ 的 shared_from_this 在 Rust 中的等价物是什么?

标签 rust

我有一个对象,我知道它在 Arc 中,因为所有实例总是 Arced。我希望能够在函数调用中传递我自己的克隆 Arc。我正在调用的对象稍后会在其他线程上给我回电。

在 C++ 中,有一个名为 enable_shared_from_this 的标准 mixin。它使我能够做到这一点

class Bus : public std::enable_shared_from_this<Bus>
{
....
   void SetupDevice(Device device,...)
   {
       device->Attach(shared_from_this());
   }
}

如果此对象不受 shared_ptr 管理(最接近的 C++ 必须为 Arc),那么这将在运行时失败。

我找不到等价物。

编辑:

这是一个为什么需要它的例子。我有一个定时器队列库。它允许客户端请求在将来的某个时间点运行任意闭包。该代码在专用线程上运行。要使用它,您必须传递要稍后执行的函数的闭包。

use std::time::{Duration, Instant};
use timerqueue::*;
use parking_lot::Mutex;
use std::sync::{Arc,Weak};
use std::ops::{DerefMut};

// inline me keeper cos not on github
pub struct MeKeeper<T> {
    them: Mutex<Weak<T>>,
}

impl<T> MeKeeper<T> {
    pub fn new() -> Self {
        Self {
            them: Mutex::new(Weak::new()),
        }
    }
    pub fn save(&self, arc: &Arc<T>) {
        *self.them.lock().deref_mut() = Arc::downgrade(arc);
    }
    pub fn get(&self) -> Arc<T> {
        match self.them.lock().upgrade() {
            Some(arc) => return arc,
            None => unreachable!(),
        }
    }
}
// -----------------------------------

struct Test {
    data:String,
    me: MeKeeper<Self>,
}

impl Test {

    pub fn new() -> Arc<Test>{
        let arc = Arc::new(Self {
            me: MeKeeper::new(),
            data: "Yo".to_string()
        });
        arc.me.save(&arc);
        arc
    }
    
    fn task(&self) {
        println!("{}", self.data);
    }

    // in real use case the TQ and a ton of other status data is passed in the new call for Test
    // to keep things simple here the 'container' passes tq as an arg

    pub fn do_stuff(&self, tq: &TimerQueue) {
        // stuff includes a async task that must be done in 1 second

        //.....
        let me = self.me.get().clone();
        tq.queue(
            Box::new(move || me.task()),
            "x".to_string(),
            Instant::now() + Duration::from_millis(1000),
        );
    }


}

fn main() {
    // in real case (PDP11 emulator) there is a Bus class owning tons of objects thats
    // alive for the whole duration
    let tq = Arc::new(TimerQueue::new());
    let test = Test::new();
    test.do_stuff(&*tq);
    // just to keep everything alive while we wait
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).unwrap();
}

cargo 运输

[package]
name = "tqclient"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
timerqueue = { git = "https://github.com/pm100/timerqueue.git" }
parking_lot = "0.11"

最佳答案

无法从 &self 到存储 selfArc。这是因为:

  1. 与 C++ 引用相比,Rust 引用具有额外的假设,这些假设会使此类转换成为未定义的行为。
  2. Rust 的 Arc 实现甚至没有公开确定 self 是否存储在 Arc 中所必需的信息。

幸运的是,还有一种替代方法。不是为 Arc 中的值创建 &self 并将其传递给方法,而是将 Arc 直接传递给需要的方法访问它。你可以这样做:

use std::sync::Arc;

struct Shared {
    field: String,
}

impl Shared {
    fn print_field(self: Arc<Self>) {
        let clone: Arc<Shared> = self.clone();
        
        println!("{}", clone.field);
    }
}

那么print_field函数只能在封装在Arc中的Shared上调用。

关于rust - C++ 的 shared_from_this 在 Rust 中的等价物是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63542263/

相关文章:

rust - Rust 如何知道需要或提供哪些特征方法?

iterator - 在向量中存储 Peekable 迭代器时无法推断出适当的生命周期

rust - 复杂泛型代码"conflicting implementations"错误,如何解决?

reference - 为什么我可以返回对局部文字的引用而不是变量?

rust - 如何遍历线程句柄并在完成后加入另一个循环?

bit-manipulation - 将负符号添加到无符号的更快方法

rust - 将相同变量绑定(bind)到共享特征的不同类型的模式

rust - 如何在没有生命周期参数的结构中存储 `regex::Match` 对象?

assembly - 如何在不影响rip相对寻址的情况下正确链接两个目标文件?

rust - 需要全面了解Rust的单元格和引用计数类型