那么,有没有一种可靠的方法可以做到这一点
对
最好不用Rc<>
哦嗯,没有.但是Rc
的开销应该可以忽略不计,这使得实现非常简单.您已经需要一个智能指针类型,因为该 struct 是递归的.
// Newtypes for implementing your alt1 and alt2 ordering.
struct Alt1Ordering(Rc<MyType>);
impl PartialEq for Alt1Ordering { ... }
impl PartialOrd for Alt1Ordering { ... }
impl Eq for Alt1Ordering {}
impl Ord for Alt1Ordering { ... }
struct Alt2Ordering(Rc<MyType>);
impl PartialEq for Alt2Ordering { ... }
impl PartialOrd for Alt2Ordering { ... }
impl Eq for Alt2Ordering {}
impl Ord for Alt2Ordering { ... }
struct MyType {
/// Ordered by insertion order.
basis: Vec<Rc<MyType>>,
/// Alternative ordering for basis.
alt1_ordering: BTreeSet<Alt1Ordering>,
/// Other alternative ordering for basis.
alt2_ordering: BTreeSet<Alt2Ordering>,
}
impl MyType {
pub fn push(&mut self, value: MyType) {
let value = Rc::new(value);
self.basis.push(value.clone());
self.alt1_ordering.insert(Alt1Ordering(value.clone()));
self.alt2_ordering.insert(Alt2Ordering(value));
}
// Whatever accessors you need, e.g.:
pub fn iter_basis(&self) -> impl Iterator<Item=&MyType> {
self.basis.iter().map(|v| &**v)
}
pub fn iter_alt1(&self) -> impl Iterator<Item=&MyType> {
self.alt1_ordering.iter().map(|v| &*v.0)
}
pub fn iter_alt2(&self) -> impl Iterator<Item=&MyType> {
self.alt2_ordering.iter().map(|v| &*v.0)
}
}
请注意,MyType
既不是Send
也不是Sync
,因为它包含Rc
.然而,只要clone
或销毁Rc
的所有方法都取&mut self
,那么实现Send
和Sync
应该是安全的,因为如果有&mut MyType
,那么就不应该存在其他引用.
请注意,您没有编写的代码可能会使Send
和Sync
实现不健全.例如,如果您#[derive(Clone)]
,编译器生成的实现将使trait实现不健全,因为它将使用共享引用克隆Rc
.
或者,您可以将Rc
替换为Arc
,以安全地获得Send
和Sync
,而无需考虑克隆/销毁Rc
的位置.
从理论上讲,不使用钉扎Rc
就可以做到这一点,但这需要unsafe
,只有当Rc
的开销被证明很重要时,我才会研究这条路径(我怀疑会是这样).