Is there a friendlier object like RefCell?

I am looking for a class similar to Vec<RefCell<T>> , since it is the ultimate owner and distributor of all its data, but different parts of the array can be repeatedly borrowed by several parties for an indefinite period.

I emphasize vaguely because Vec<T> chunks can also be borrowed by several parties, but there is a separation that can only be resolved after the parties are borrowed.

Vec<RefCell<T>> seems like a world of danger and a lot of ugly if checking borrow_state , which seems to be unstable . If you do something wrong, then cabalmo! Panic! This is not what the lending library likes. In the lending library, if you ask for a book that isn't there, they tell you, "Oh, it's written out." No one dies in an explosion.

So I would like to write code something like this:

 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 

Is there such a thing? Or is there another canonical way to get this behavior? Some kind of "friendly RefCell"?

If the answer is yes, is there also a streaming option?

+5
source share
2 answers

RefCell not intended for long- RefCell borrowing. A typical use case is that in a function you will take RefCell (either with a change, or invariably), work with a value, and then release the debt before returning. I'm curious to see how you hope to recover from a RefCell in a single-threaded context.

Stream equivalent of RefCell RwLock . It has try_read and try_write functions that do not block or panic if an incompatible lock is still received (in any thread, including the current thread). In contrast to RefCell , it makes sense to simply try again later if the RwLock lock fails because another thread may just block it at the same time.

If you always use write or try_write and never read or try_read , then you should probably use the simpler Mutex instead.

+2
source
 #![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 } 

Currently, night work is required.

+1
source

Source: https://habr.com/ru/post/1234619/


All Articles