forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of rust-lang#136772 - safinaskar:parallel-2025-02-08-11-55…
…, r=<try> [perf run] parallel: rustc_data_structures: sync: implement RwLock as enum { Sync(parking_lot::RwLock), NoSync(RefCell) } Please, somebody, run perf. parallel: rustc_data_structures: sync: implement `RwLock` as `enum { Sync(parking_lot::RwLock), NoSync(RefCell) }` Hopefully this will make single threaded front end faster. I carefully split changes into commits. Commit messages are self-explanatory. Squashing is not recommended. cc "Parallel Rustc Front-end" rust-lang#113349 r? SparrowLii `@rustbot` label: +WG-compiler-parallel
- Loading branch information
Showing
3 changed files
with
279 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,271 @@ | ||
use std::cell::{Ref, RefCell, RefMut}; | ||
use std::intrinsics::unlikely; | ||
use std::ops::{Deref, DerefMut}; | ||
|
||
use crate::sync::mode::might_be_dyn_thread_safe; | ||
|
||
#[derive(Debug)] | ||
pub enum RwLock<T> { | ||
Sync(parking_lot::RwLock<T>), | ||
NoSync(RefCell<T>), | ||
} | ||
|
||
#[clippy::has_significant_drop] | ||
#[must_use = "if unused the RwLock will immediately unlock"] | ||
#[derive(Debug)] | ||
pub enum ReadGuard<'a, T> { | ||
Sync(parking_lot::RwLockReadGuard<'a, T>), | ||
NoSync(Ref<'a, T>), | ||
} | ||
|
||
#[clippy::has_significant_drop] | ||
#[must_use = "if unused the RwLock will immediately unlock"] | ||
#[derive(Debug)] | ||
pub enum WriteGuard<'a, T> { | ||
Sync(parking_lot::RwLockWriteGuard<'a, T>), | ||
NoSync(RefMut<'a, T>), | ||
} | ||
|
||
#[clippy::has_significant_drop] | ||
#[must_use = "if unused the RwLock will immediately unlock"] | ||
#[derive(Debug)] | ||
pub enum MappedReadGuard<'a, T> { | ||
Sync(parking_lot::MappedRwLockReadGuard<'a, T>), | ||
NoSync(Ref<'a, T>), | ||
} | ||
|
||
#[clippy::has_significant_drop] | ||
#[must_use = "if unused the RwLock will immediately unlock"] | ||
#[derive(Debug)] | ||
pub enum MappedWriteGuard<'a, T> { | ||
Sync(parking_lot::MappedRwLockWriteGuard<'a, T>), | ||
NoSync(RefMut<'a, T>), | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct ReadError; | ||
|
||
#[derive(Debug)] | ||
pub struct WriteError; | ||
|
||
impl<T> RwLock<T> { | ||
#[inline(always)] | ||
pub fn new(inner: T) -> Self { | ||
if unlikely(might_be_dyn_thread_safe()) { | ||
RwLock::Sync(parking_lot::RwLock::new(inner)) | ||
} else { | ||
RwLock::NoSync(RefCell::new(inner)) | ||
} | ||
} | ||
|
||
#[inline(always)] | ||
pub fn into_inner(self) -> T { | ||
match self { | ||
RwLock::Sync(inner) => parking_lot::RwLock::into_inner(inner), | ||
RwLock::NoSync(inner) => RefCell::into_inner(inner), | ||
} | ||
} | ||
|
||
#[inline(always)] | ||
pub fn get_mut(&mut self) -> &mut T { | ||
match self { | ||
RwLock::Sync(inner) => parking_lot::RwLock::get_mut(inner), | ||
RwLock::NoSync(inner) => RefCell::get_mut(inner), | ||
} | ||
} | ||
|
||
#[inline(always)] | ||
#[track_caller] | ||
pub fn read(&self) -> ReadGuard<'_, T> { | ||
match self { | ||
RwLock::Sync(inner) => ReadGuard::Sync(inner.read()), | ||
RwLock::NoSync(inner) => ReadGuard::NoSync(inner.borrow()), | ||
} | ||
} | ||
|
||
#[inline(always)] | ||
pub fn try_read(&self) -> Result<ReadGuard<'_, T>, ReadError> { | ||
match self { | ||
RwLock::Sync(inner) => Ok(ReadGuard::Sync(inner.try_read().ok_or(ReadError)?)), | ||
RwLock::NoSync(inner) => { | ||
Ok(ReadGuard::NoSync(inner.try_borrow().map_err(|_| ReadError)?)) | ||
} | ||
} | ||
} | ||
|
||
#[inline(always)] | ||
#[track_caller] | ||
pub fn write(&self) -> WriteGuard<'_, T> { | ||
match self { | ||
RwLock::Sync(inner) => WriteGuard::Sync(inner.write()), | ||
RwLock::NoSync(inner) => WriteGuard::NoSync(inner.borrow_mut()), | ||
} | ||
} | ||
|
||
#[inline(always)] | ||
pub fn try_write(&self) -> Result<WriteGuard<'_, T>, WriteError> { | ||
match self { | ||
RwLock::Sync(inner) => Ok(WriteGuard::Sync(inner.try_write().ok_or(WriteError)?)), | ||
RwLock::NoSync(inner) => { | ||
Ok(WriteGuard::NoSync(inner.try_borrow_mut().map_err(|_| WriteError)?)) | ||
} | ||
} | ||
} | ||
|
||
#[inline(always)] | ||
#[track_caller] | ||
pub fn borrow(&self) -> ReadGuard<'_, T> { | ||
self.read() | ||
} | ||
|
||
#[inline(always)] | ||
pub fn try_borrow(&self) -> Result<ReadGuard<'_, T>, ReadError> { | ||
self.try_read() | ||
} | ||
|
||
#[inline(always)] | ||
#[track_caller] | ||
pub fn borrow_mut(&self) -> WriteGuard<'_, T> { | ||
self.write() | ||
} | ||
|
||
#[inline(always)] | ||
pub fn try_borrow_mut(&self) -> Result<WriteGuard<'_, T>, WriteError> { | ||
self.try_write() | ||
} | ||
} | ||
|
||
impl<T: Default> Default for RwLock<T> { | ||
#[inline(always)] | ||
fn default() -> Self { | ||
RwLock::<T>::new(Default::default()) | ||
} | ||
} | ||
|
||
impl<'a, T> ReadGuard<'a, T> { | ||
#[inline(always)] | ||
pub fn map<U, F>(s: Self, f: F) -> MappedReadGuard<'a, U> | ||
where | ||
F: FnOnce(&T) -> &U, | ||
{ | ||
match s { | ||
ReadGuard::Sync(guard) => { | ||
MappedReadGuard::Sync(parking_lot::RwLockReadGuard::map(guard, f)) | ||
} | ||
ReadGuard::NoSync(guard) => MappedReadGuard::NoSync(Ref::map(guard, f)), | ||
} | ||
} | ||
} | ||
|
||
impl<'a, T> WriteGuard<'a, T> { | ||
#[inline(always)] | ||
pub fn map<U, F>(s: Self, f: F) -> MappedWriteGuard<'a, U> | ||
where | ||
F: FnOnce(&mut T) -> &mut U, | ||
{ | ||
match s { | ||
WriteGuard::Sync(guard) => { | ||
MappedWriteGuard::Sync(parking_lot::RwLockWriteGuard::map(guard, f)) | ||
} | ||
WriteGuard::NoSync(guard) => MappedWriteGuard::NoSync(RefMut::map(guard, f)), | ||
} | ||
} | ||
} | ||
|
||
impl<'a, T> Deref for ReadGuard<'a, T> { | ||
type Target = T; | ||
|
||
#[inline(always)] | ||
fn deref(&self) -> &T { | ||
match self { | ||
ReadGuard::Sync(guard) => Deref::deref(guard), | ||
ReadGuard::NoSync(guard) => Deref::deref(guard), | ||
} | ||
} | ||
} | ||
|
||
impl<'a, T> Deref for WriteGuard<'a, T> { | ||
type Target = T; | ||
|
||
#[inline(always)] | ||
fn deref(&self) -> &T { | ||
match self { | ||
WriteGuard::Sync(guard) => Deref::deref(guard), | ||
WriteGuard::NoSync(guard) => Deref::deref(guard), | ||
} | ||
} | ||
} | ||
|
||
impl<'a, T> DerefMut for WriteGuard<'a, T> { | ||
#[inline(always)] | ||
fn deref_mut(&mut self) -> &mut T { | ||
match self { | ||
WriteGuard::Sync(guard) => DerefMut::deref_mut(guard), | ||
WriteGuard::NoSync(guard) => DerefMut::deref_mut(guard), | ||
} | ||
} | ||
} | ||
|
||
impl<'a, T> MappedReadGuard<'a, T> { | ||
#[inline(always)] | ||
pub fn map<U, F>(s: Self, f: F) -> MappedReadGuard<'a, U> | ||
where | ||
F: FnOnce(&T) -> &U, | ||
{ | ||
match s { | ||
MappedReadGuard::Sync(guard) => { | ||
MappedReadGuard::Sync(parking_lot::MappedRwLockReadGuard::map(guard, f)) | ||
} | ||
MappedReadGuard::NoSync(guard) => MappedReadGuard::NoSync(Ref::map(guard, f)), | ||
} | ||
} | ||
} | ||
|
||
impl<'a, T> MappedWriteGuard<'a, T> { | ||
#[inline(always)] | ||
pub fn map<U, F>(s: Self, f: F) -> MappedWriteGuard<'a, U> | ||
where | ||
F: FnOnce(&mut T) -> &mut U, | ||
{ | ||
match s { | ||
MappedWriteGuard::Sync(guard) => { | ||
MappedWriteGuard::Sync(parking_lot::MappedRwLockWriteGuard::map(guard, f)) | ||
} | ||
MappedWriteGuard::NoSync(guard) => MappedWriteGuard::NoSync(RefMut::map(guard, f)), | ||
} | ||
} | ||
} | ||
|
||
impl<'a, T> Deref for MappedReadGuard<'a, T> { | ||
type Target = T; | ||
|
||
#[inline(always)] | ||
fn deref(&self) -> &T { | ||
match self { | ||
MappedReadGuard::Sync(guard) => Deref::deref(guard), | ||
MappedReadGuard::NoSync(guard) => Deref::deref(guard), | ||
} | ||
} | ||
} | ||
|
||
impl<'a, T> Deref for MappedWriteGuard<'a, T> { | ||
type Target = T; | ||
|
||
#[inline(always)] | ||
fn deref(&self) -> &T { | ||
match self { | ||
MappedWriteGuard::Sync(guard) => Deref::deref(guard), | ||
MappedWriteGuard::NoSync(guard) => Deref::deref(guard), | ||
} | ||
} | ||
} | ||
|
||
impl<'a, T> DerefMut for MappedWriteGuard<'a, T> { | ||
#[inline(always)] | ||
fn deref_mut(&mut self) -> &mut T { | ||
match self { | ||
MappedWriteGuard::Sync(guard) => DerefMut::deref_mut(guard), | ||
MappedWriteGuard::NoSync(guard) => DerefMut::deref_mut(guard), | ||
} | ||
} | ||
} |
Oops, something went wrong.