gpt4 book ai didi

rust - 如何使用 Arc> 转换特征对象?

转载 作者:行者123 更新时间:2023-11-29 08:03:47 26 4
gpt4 key购买 nike

我正在尝试调用一个函数,该函数接受一个指向 Mutex 的指针。一些特征对象,我希望能够为 Mutex 实现特征该特征对象允许处理 Mutex作为特征对象的实例进行抽象。

举个例子,想象一个 Event监听器设置如下:

use std::sync::{Arc, Mutex, Weak};

// Define a simple event
trait Event: Send + Sync + 'static {}
impl Event for String {}


// Define the listener interface
trait Listener<E: Event> {
fn notify(&self, event: &E);
}

// Extend the listener interface to listenrs wrapped by a mutex
impl<E: Event> Listener<E> for Mutex<Listener<E>> {
fn notify(&self, event: &E) {
self.lock().unwrap().notify(event);
}
}


// Contrived thing to listen for messages
struct Console;
impl Listener<String> for Console {
fn notify(&self, event: &String) {
println!("{}", event);
}
}


// Simple function which may be called asynchronously and then sends a message
// when it is complete
fn do_stuff(l: Arc<Listener<String>>) {
// Would normally cast to a Weak<...> and then store in a list of listneners
// For some sort of object
let m = String::from("I did stuff!");
l.notify(&m);
}

fn main() {
let l: Arc<Mutex<Console>> = Arc::new(Mutex::new(Console));

let t1 = Arc::clone(&l) as Arc<Mutex<Listener<String>>>; //this part is ok
// Here is where we run into issues... This *should* be equvlient to
// do_stuff(t1), but with the corercion explicit
let t2 = Arc::clone(&t1) as Arc<Listener<String>>;
do_stuff(t2);

// This is a simple, working example of it interpreting a Mutex<Listener<E>>
// as just a Listener<E>
let m = String::from("Somthing else...");
(l as Arc<Mutex<Listener<String>>>).notify(&m);
}

( Playground )

问题是:

error[E0277]: the trait bound `Listener<std::string::String>: std::marker::Sized` is not satisfied in `std::sync::Mutex<Listener<std::string::String>>`
--> src/main.rs:45:14
|
45 | let t2 = Arc::clone(&t1) as Arc<Listener<String>>;
| ^^^^^^^^^^^^^^^ `Listener<std::string::String>` does not have a constant size known at compile-time
|
= help: within `std::sync::Mutex<Listener<std::string::String>>`, the trait `std::marker::Sized` is not implemented for `Listener<std::string::String>`
= note: required because it appears within the type `std::sync::Mutex<Listener<std::string::String>>`
= note: required for the cast to the object type `Listener<std::string::String>`

为什么会这样?自Arc是一个指向数据的指针,按我的理解,它应该可以指向一个Listener<String>这恰好是 Listener<Mutex<String>> .

我看到至少有两种方法可以避免这种情况,第一种是简单地 impl Listener<String> for Mutex<Listener<String>> ,但是,在实际代码中,这可能需要相互依赖,这应该避免,因为只能在定义特征或结构的地方实现特征(并且 Mutex 未在我的代码中定义)。

第二个是移动Mutex进入Listener对象,因此调用者根本不需要转换它。这会起作用,并且可能是更好的解决方案。尽管如此,我还是很好奇为什么建议的类型转换不起作用,或者可以改变什么来让它起作用。

最佳答案

Since an Arc is a pointer to data, from my understanding, it should be able to point to a Listener<String>

是的,这是真的。我相信你的问题是你(不小心?)要求你有一个 Mutex<Listener<String>>在某一点。这是有效的,因为 Mutex 中的值不在指针后面,因此使整个类型变小。

Arc<Mutex<Listener<String>>> 很好虽然。

相反,我会为 Mutex 实现特征实现相同特征的任何种类。我会对引用资料和 Box 做同样的事情ed 特征的特征对象也是如此。在所有情况下,我都会删除 Sized必须允许特征对象:

use std::sync::{Arc, Mutex};

trait Event: Send + Sync + 'static {}
impl Event for String {}

trait Listener<E: Event> {
fn notify(&self, event: &E);
}

impl<L, E> Listener<E> for Mutex<L>
where
L: ?Sized + Listener<E>,
E: Event,
{
fn notify(&self, event: &E) {
self.lock().unwrap().notify(event);
}
}

impl<'a, L, E> Listener<E> for &'a L
where
L: ?Sized + Listener<E>,
E: Event,
{
fn notify(&self, event: &E) {
(**self).notify(event);
}
}

struct Console;
impl Listener<String> for Console {
fn notify(&self, event: &String) {
println!("{}", event);
}
}

fn do_stuff(l: Arc<Listener<String>>) {
let m = String::from("I did stuff!");
l.notify(&m);
}

fn main() {
let l: Arc<Mutex<Console>> = Arc::new(Mutex::new(Console));
let l2 = Arc::clone(&l) as Arc<Listener<String>>;
let l3 = Arc::clone(&l) as Arc<Listener<String>>;

do_stuff(l);
do_stuff(l2);

let m = String::from("Something else...");
l3.notify(&m);
}

关于rust - 如何使用 Arc<Mutex<...>> 转换特征对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47382154/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com