mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Implement AtomicRef::map.
MozReview-Commit-ID: 8iOALQylOuK
This commit is contained in:
parent
cf9d282914
commit
d252c8e42a
3 changed files with 113 additions and 4 deletions
|
@ -2,7 +2,11 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
|
use owning_ref::{OwningRef, StableAddress};
|
||||||
use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
/// Container type providing RefCell-like semantics for objects shared across
|
/// Container type providing RefCell-like semantics for objects shared across
|
||||||
/// threads.
|
/// threads.
|
||||||
|
@ -20,17 +24,41 @@ use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||||
/// RefCell, so we newtype it with some API sugar.
|
/// RefCell, so we newtype it with some API sugar.
|
||||||
pub struct AtomicRefCell<T>(RwLock<T>);
|
pub struct AtomicRefCell<T>(RwLock<T>);
|
||||||
|
|
||||||
pub type AtomicRef<'a, T> = RwLockReadGuard<'a, T>;
|
pub struct AtomicRef<'a, T: 'a>(RwLockReadGuard<'a, T>);
|
||||||
pub type AtomicRefMut<'a, T> = RwLockWriteGuard<'a, T>;
|
unsafe impl<'a, T> StableAddress for AtomicRef<'a, T> {}
|
||||||
|
|
||||||
|
impl<'a, T> Deref for AtomicRef<'a, T> {
|
||||||
|
type Target = T;
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
self.0.deref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AtomicRefMut<'a, T: 'a>(RwLockWriteGuard<'a, T>);
|
||||||
|
unsafe impl<'a, T> StableAddress for AtomicRefMut<'a, T> {}
|
||||||
|
|
||||||
|
impl<'a, T> Deref for AtomicRefMut<'a, T> {
|
||||||
|
type Target = T;
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
self.0.deref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> DerefMut for AtomicRefMut<'a, T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut T {
|
||||||
|
self.0.deref_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> AtomicRefCell<T> {
|
impl<T> AtomicRefCell<T> {
|
||||||
pub fn new(value: T) -> Self {
|
pub fn new(value: T) -> Self {
|
||||||
AtomicRefCell(RwLock::new(value))
|
AtomicRefCell(RwLock::new(value))
|
||||||
}
|
}
|
||||||
pub fn borrow(&self) -> AtomicRef<T> {
|
pub fn borrow(&self) -> AtomicRef<T> {
|
||||||
self.0.try_read().expect("already mutably borrowed")
|
AtomicRef(self.0.try_read().expect("already mutably borrowed"))
|
||||||
}
|
}
|
||||||
pub fn borrow_mut(&self) -> AtomicRefMut<T> {
|
pub fn borrow_mut(&self) -> AtomicRefMut<T> {
|
||||||
self.0.try_write().expect("already borrowed")
|
AtomicRefMut(self.0.try_write().expect("already borrowed"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,3 +67,42 @@ impl<T: Default> Default for AtomicRefCell<T> {
|
||||||
Self::new(T::default())
|
Self::new(T::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implement Ref{,Mut}::map()-like semantics for AtomicRef{,Mut}. We can't quite
|
||||||
|
* use AtomicRef{,Mut} as the mapped type, but we can use some trait tricks to
|
||||||
|
* allow us to pass MappedAtomicRef{,Mut} back into AtomicRef{,Mut}::map().
|
||||||
|
*
|
||||||
|
* Note: We cannot implement an AtomicRefMut::map() method until we have mutable
|
||||||
|
* OwningRef. See https://github.com/Kimundi/owning-ref-rs/pull/16
|
||||||
|
*/
|
||||||
|
pub type MappedAtomicRef<'a, T: 'a, U: 'a> = OwningRef<AtomicRef<'a, T>, U>;
|
||||||
|
|
||||||
|
pub trait Map<'a, Base, Curr> {
|
||||||
|
fn map<New, F>(self, f: F) -> MappedAtomicRef<'a, Base, New>
|
||||||
|
where F: FnOnce(&Curr) -> &New;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Base> Map<'a, Base, Base> for AtomicRef<'a, Base> {
|
||||||
|
fn map<New, F>(self, f: F) -> MappedAtomicRef<'a, Base, New>
|
||||||
|
where F: FnOnce(&Base) -> &New
|
||||||
|
{
|
||||||
|
OwningRef::new(self).map(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Base, Curr> Map<'a, Base, Curr> for MappedAtomicRef<'a, Base, Curr> {
|
||||||
|
fn map<New, F>(self, f: F) -> MappedAtomicRef<'a, Base, New>
|
||||||
|
where F: FnOnce(&Curr) -> &New
|
||||||
|
{
|
||||||
|
self.map(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Base> AtomicRef<'a, Base> {
|
||||||
|
pub fn map<Curr, New, M, F>(orig: M, f: F) -> MappedAtomicRef<'a, Base, New>
|
||||||
|
where F: FnOnce(&Curr) -> &New, M: Map<'a, Base, Curr>
|
||||||
|
{
|
||||||
|
orig.map(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
41
tests/unit/style/atomic_refcell.rs
Normal file
41
tests/unit/style/atomic_refcell.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use style::atomic_refcell::{AtomicRef, AtomicRefCell};
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
u: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Bar {
|
||||||
|
f: Foo,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn map() {
|
||||||
|
let a = AtomicRefCell::new(Bar { f: Foo { u: 42 } });
|
||||||
|
let b = a.borrow();
|
||||||
|
assert_eq!(b.f.u, 42);
|
||||||
|
let c = AtomicRef::map(b, |x| &x.f);
|
||||||
|
assert_eq!(c.u, 42);
|
||||||
|
let d = AtomicRef::map(c, |x| &x.u);
|
||||||
|
assert_eq!(*d, 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME(bholley): Enable once we have AtomicRefMut::map(), which is blocked on
|
||||||
|
* https://github.com/Kimundi/owning-ref-rs/pull/16
|
||||||
|
#[test]
|
||||||
|
fn map_mut() {
|
||||||
|
let a = AtomicRefCell::new(Bar { f: Foo { u: 42 } });
|
||||||
|
let mut b = a.borrow_mut();
|
||||||
|
assert_eq!(b.f.u, 42);
|
||||||
|
b.f.u = 43;
|
||||||
|
let mut c = AtomicRefMut::map(b, |x| &x.f);
|
||||||
|
assert_eq!(c.u, 43);
|
||||||
|
c.u = 44;
|
||||||
|
let mut d = AtomicRefMut::map(c, |x| &x.u);
|
||||||
|
assert_eq!(*d, 44);
|
||||||
|
*d. = 45;
|
||||||
|
assert_eq!(*d, 45);
|
||||||
|
}*/
|
|
@ -19,6 +19,7 @@ extern crate style_traits;
|
||||||
extern crate url;
|
extern crate url;
|
||||||
extern crate util;
|
extern crate util;
|
||||||
|
|
||||||
|
mod atomic_refcell;
|
||||||
mod attr;
|
mod attr;
|
||||||
mod cache;
|
mod cache;
|
||||||
mod logical_geometry;
|
mod logical_geometry;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue