我正在寻找一个类似于Vec<RefCell<T>>
的课程,因为它是最终的所有者&amp;所有数据的分配器,但阵列的不同部分可以由多方无限地可靠地借用。
我强调无限期因为当然Vec<T>
的部分也可以被多方共同借用,但这样做涉及进行分割,只有在各方借款后才能解决
Vec<RefCell<T>>
似乎是一个充满危险的世界,许多丑陋的if
语句检查borrow_state
,似乎是unstable。如果你做错了什么,那么kablammo!恐慌!这不是借阅图书馆的样子。在借阅图书馆,如果你要求一本不存在的书,他们会告诉你“哦,它已经签出了。”爆炸中没有人死亡。
所以我想编写类似这样的代码:
let mut a = LendingLibrary::new();
a.push(Foo{x:10});
a.push(Foo{x:11});
let b1 = a.get(0); // <-- b1 is an Option<RefMut<Foo>>
let b2 = a.get(1); // <-- b2 is an Option<RefMut<Foo>>
// the 0th element has already been borrowed, so...
let b3 = a.get(0); // <-- b3 is Option::None
这样的事情存在吗?或者是否有另一种规范方式来获得这种行为?一种“友好的RefCell”?
如果答案是肯定的,那还有一个线程安全变体吗?
答案 0 :(得分:2)
RefCell
并非专为长期借用而设计。典型的用例是,在函数中,您将借用RefCell
(可变或不可变),使用该值,然后在返回之前释放借位。我很想知道您希望如何在单线程环境中从借用的RefCell
中恢复。
与RefCell
等效的线程安全是RwLock
。它具有try_read
和try_write
函数,如果仍然获取不兼容的锁(在任何线程上,包括当前线程),它们不会阻塞或发生混乱。与RefCell
相反,如果锁定RwLock
失败,则稍后重试是有意义的,因为另一个线程可能恰好同时锁定了它。
如果您最终总是使用write
或try_write
,而不是read
或try_read
,那么您应该使用更简单的Mutex
。< / p>
答案 1 :(得分:1)
#![feature(borrow_state)]
use std::cell::{RefCell, RefMut, BorrowState};
struct LendingLibrary<T> {
items: Vec<RefCell<T>>
}
impl<T> LendingLibrary<T> {
fn new(items: Vec<T>) -> LendingLibrary<T> {
LendingLibrary {
items: items.into_iter().map(|e| RefCell::new(e)).collect()
}
}
fn get(&self, item: usize) -> Option<RefMut<T>> {
self.items.get(item)
.and_then(|cell| match cell.borrow_state() {
BorrowState::Unused => Some(cell.borrow_mut()),
_ => None
})
}
}
fn main() {
let lib = LendingLibrary::new(vec![1, 2, 3]);
let a = lib.get(0); // Some
let b = lib.get(1); // Some
let a2 = lib.get(0); // None
}
这需要每晚发布才能使用。