Auto merge of #59211 - nox:refcell-borrow-state, r=KodrAus
Introduce RefCell::try_borrow_unguarded *Come sit next to the fireplace with me, this is going to be a long story.* So, you may already be aware that Servo has weird design constraints that forces us developers working on it to do weird things. The thing that interests us today is that we do layout on a separate thread with its own thread pool to do some things in parallel, whereas the data it uses comes from the script thread, which implements the entire DOM and related pieces, with `!Sync` data types such as `RefCell<T>`. The invariant we maintain is that script does not do anything ever with the DOM data as long as layout is doing its job. That's all nice and all, but one thing we don't ensure is that we don't actually know if script was currently mutably borrowing some `RefCell<T>` prior to starting layout, which may lead to aliasing mutable memory and obviously undefined behaviour. This PR reinstates `RefCell::borrow_state` so that [this method](https://github.com/servo/servo/blob/master/components/script/dom/bindings/cell.rs#L23-L30) can make use of it and return `None` if the cell was mutably borrowed. Cc @SimonSapin
This commit is contained in:
commit
850912704e
@ -0,0 +1,7 @@
|
||||
# `borrow_state`
|
||||
|
||||
The tracking issue for this feature is: [#27733]
|
||||
|
||||
[#27733]: https://github.com/rust-lang/rust/issues/27733
|
||||
|
||||
------------------------
|
@ -955,6 +955,44 @@ impl<T: ?Sized> RefCell<T> {
|
||||
&mut *self.value.get()
|
||||
}
|
||||
}
|
||||
|
||||
/// Immutably borrows the wrapped value, returning an error if the value is
|
||||
/// currently mutably borrowed.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unlike `RefCell::borrow`, this method is unsafe because it does not
|
||||
/// return a `Ref`, thus leaving the borrow flag untouched. Mutably
|
||||
/// borrowing the `RefCell` while the reference returned by this method
|
||||
/// is alive is undefined behaviour.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(borrow_state)]
|
||||
/// use std::cell::RefCell;
|
||||
///
|
||||
/// let c = RefCell::new(5);
|
||||
///
|
||||
/// {
|
||||
/// let m = c.borrow_mut();
|
||||
/// assert!(unsafe { c.try_borrow_unguarded() }.is_err());
|
||||
/// }
|
||||
///
|
||||
/// {
|
||||
/// let m = c.borrow();
|
||||
/// assert!(unsafe { c.try_borrow_unguarded() }.is_ok());
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "borrow_state", issue = "27733")]
|
||||
#[inline]
|
||||
pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> {
|
||||
if !is_writing(self.borrow.get()) {
|
||||
Ok(&*self.value.get())
|
||||
} else {
|
||||
Err(BorrowError { _private: () })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
Loading…
Reference in New Issue
Block a user