Skip to content
76 changes: 10 additions & 66 deletions compiler/rustc_data_structures/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,26 @@
use std::collections::HashMap;
use std::hash::{BuildHasher, Hash};

pub use parking_lot::{
MappedRwLockReadGuard as MappedReadGuard, MappedRwLockWriteGuard as MappedWriteGuard,
RwLockReadGuard as ReadGuard, RwLockWriteGuard as WriteGuard,
};

pub use self::atomic::AtomicU64;
pub use self::freeze::{FreezeLock, FreezeReadGuard, FreezeWriteGuard};
#[doc(no_inline)]
pub use self::lock::{Lock, LockGuard, Mode};
pub use self::lock::{Lock, LockGuard};
pub use self::mode::{
FromDyn, check_dyn_thread_safe, is_dyn_thread_safe, set_dyn_thread_safe_mode,
FromDyn, Mode, check_dyn_thread_safe, is_dyn_thread_safe, set_dyn_thread_safe_mode,
};
pub use self::parallel::{
broadcast, par_fns, par_for_each_in, par_for_each_slice, par_join, par_map, parallel_guard,
spawn, try_par_for_each_in,
};
pub use self::rw_lock::{MappedReadGuard, MappedWriteGuard, ReadGuard, RwLock, WriteGuard};
pub use self::vec::{AppendOnlyIndexVec, AppendOnlyVec};
pub use self::worker_local::{Registry, WorkerLocal};
pub use crate::marker::*;

mod freeze;
mod lock;
mod parallel;
mod rw_lock;
mod vec;
mod worker_local;

Expand All @@ -68,6 +65,12 @@ mod mode {

use crate::sync::{DynSend, DynSync};

#[derive(Clone, Copy, PartialEq)]
pub enum Mode {
NoSync,
Sync,
}

const UNINITIALIZED: u8 = 0;
const DYN_NOT_THREAD_SAFE: u8 = 1;
const DYN_THREAD_SAFE: u8 = 2;
Expand Down Expand Up @@ -149,10 +152,6 @@ mod mode {
}
}

/// This makes locks panic if they are already held.
/// It is only useful when you are running in a single thread
const ERROR_CHECKING: bool = false;

#[derive(Default)]
#[repr(align(64))]
pub struct CacheAligned<T>(pub T);
Expand All @@ -168,58 +167,3 @@ impl<K: Eq + Hash, V: Eq, S: BuildHasher> HashMapExt<K, V> for HashMap<K, V, S>
self.entry(key).and_modify(|old| assert!(*old == value)).or_insert(value);
}
}

#[derive(Debug, Default)]
pub struct RwLock<T>(parking_lot::RwLock<T>);

impl<T> RwLock<T> {
#[inline(always)]
pub fn new(inner: T) -> Self {
RwLock(parking_lot::RwLock::new(inner))
}

#[inline(always)]
pub fn into_inner(self) -> T {
self.0.into_inner()
}

#[inline(always)]
pub fn get_mut(&mut self) -> &mut T {
self.0.get_mut()
}

#[inline(always)]
pub fn read(&self) -> ReadGuard<'_, T> {
if ERROR_CHECKING {
self.0.try_read().expect("lock was already held")
} else {
self.0.read()
}
}

#[inline(always)]
pub fn try_write(&self) -> Result<WriteGuard<'_, T>, ()> {
self.0.try_write().ok_or(())
}

#[inline(always)]
pub fn write(&self) -> WriteGuard<'_, T> {
if ERROR_CHECKING {
self.0.try_write().expect("lock was already held")
} else {
self.0.write()
}
}

#[inline(always)]
#[track_caller]
pub fn borrow(&self) -> ReadGuard<'_, T> {
self.read()
}

#[inline(always)]
#[track_caller]
pub fn borrow_mut(&self) -> WriteGuard<'_, T> {
self.write()
}
}
10 changes: 2 additions & 8 deletions compiler/rustc_data_structures/src/sync/lock.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
//! This module implements a lock which only uses synchronization if `might_be_dyn_thread_safe` is true.
//! It implements `DynSend` and `DynSync` instead of the typical `Send` and `Sync` traits.

use std::{fmt, hint};

#[derive(Clone, Copy, PartialEq)]
pub enum Mode {
NoSync,
Sync,
}

use std::cell::{Cell, UnsafeCell};
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ops::{Deref, DerefMut};
use std::{fmt, hint};

use mode::Mode;
use parking_lot::RawMutex;
use parking_lot::lock_api::RawMutex as _;

Expand Down
16 changes: 11 additions & 5 deletions compiler/rustc_data_structures/src/sync/parallel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,18 @@ pub fn par_for_each_in<I: DynSend, T: IntoIterator<Item = I>>(
});
}

// FIXME: actually make parallel and `T: DynSend`
pub fn par_for_each_slice<T>(items: &mut [T], for_each: impl Fn(&mut T)) {
pub fn par_for_each_slice<T: DynSend>(
items: &mut [T],
for_each: impl Fn(&mut T) + DynSync + DynSend,
) {
parallel_guard(|guard| {
items.iter_mut().for_each(|i| {
guard.run(|| for_each(i));
});
if let Some(proof) = mode::check_dyn_thread_safe() {
par_slice(items, guard, |i| for_each(i), proof)
} else {
items.iter_mut().for_each(|i| {
guard.run(|| for_each(i));
});
}
});
}

Expand Down
Loading
Loading