我正在努力在 Rust 中实现一个能够容纳
Rc<RefCell<T>>
或 Arc<RwLock<T>>
的结构。
这样设计的动机是让用户在代码将在单线程中运行时使用更便宜且更快的
Rc<RefCell<T>>
,并且仅在需要并行化时才转到Arc<RwLock<T>>
。
这就是我现在正在做的事情:
struct Structure {}
struct Sel<R,DR>
where
R: Deref<Target=DR>,
DR: Borrow<Structure>,
{
structure: R,
}
impl<R,DR> Sel<R,DR>
where
R: Deref<Target=DR>,
DR: Borrow<Structure>,
{
fn new(structure: R) -> Self {
Self{structure}
}
}
fn main() {
let st = Rc::new(RefCell::new(Structure{}));
let sel = Sel::new(st);
}
结构 Sel 可以保存任何类型 R,该类型 R 可以取消引用任何类型 DR,而 DR 又实现 Borrow(Structure 是要包装的用户类型)。理论上
Rc<RefCell<T>>
和 Arc<RwLock<T>>
都应该满足这些特征界限,但是编译器对我大喊:
error[E0277]: the trait bound `RefCell<Structure>: Borrow<Structure>` is not satisfied
--> src/main.rs:26:15
|
26 | let sel = Sel::new(st);
| ^^^^^^^^ the trait `Borrow<Structure>` is not implemented for `RefCell<Structure>`
执行此操作的正确方法是什么?我可以使用哪个特征界限来表达 DR 可以用来代替 &Structure?
在评论中给出一些出色的提示后,我找到了一个解决方案,该解决方案似乎足够通用,足以证明为其创建板条箱是合理的。 我称之为 UniRcLock。
它基于定义
Rc<RefCell<T>>
和Arc<RwLock<T>>
的共同特征的想法。该实现需要一些具有通用关联类型的高级特征魔法,允许处理生命周期并以通用方式表达作用域读写访问防护的行为。
它可以像这样使用(从crate文档复制粘贴):
#[derive(Debug)]
struct Foo(i32);
fn incr_foo(v: impl UniRcLock<Foo>){
v.write().0 += 1;
}
// Using Rc
let ptr1 = Rc::new(RefCell::new(Foo(0)));
incr_foo(ptr1.clone());
println!("After increment: {:?}", ptr1);
// Using Arc
let ptr2 = Arc::new(RwLock::new(Foo(0)));
incr_foo(ptr2.clone());
println!("After increment: {:?}", ptr2);
我希望它有用:)