1
Fork 0

Improve the rustc_data_structures::sync module doc comment.

Also, `MTRef<'a, T>` is a typedef for a reference to a `T`, but in
practice it's only used (and useful) in combination with `MTLock`, i.e.
`MTRef<'a, MTLock<T>>`. So this commit changes it to be a typedef for a
reference to an `MTLock<T>`, and renames it as `MTLockRef`. I think this
clarifies things, because I found `MTRef` quite puzzling at first.
This commit is contained in:
Nicholas Nethercote 2023-03-30 10:57:44 +11:00
parent 478cbb42b7
commit eeb5b782a6
2 changed files with 44 additions and 19 deletions

View file

@ -1,21 +1,46 @@
//! This module defines types which are thread safe if cfg!(parallel_compiler) is true. //! This module defines various operations and types that are implemented in
//! one way for the serial compiler, and another way the parallel compiler.
//! //!
//! `Lrc` is an alias of `Arc` if cfg!(parallel_compiler) is true, `Rc` otherwise. //! Operations
//! ----------
//! The parallel versions of operations use Rayon to execute code in parallel,
//! while the serial versions degenerate straightforwardly to serial execution.
//! The operations include `join`, `parallel`, `par_iter`, and `par_for_each`.
//! //!
//! `Lock` is a mutex. //! `rustc_erase_owner!` erases an `OwningRef` owner into `Erased` for the
//! It internally uses `parking_lot::Mutex` if cfg!(parallel_compiler) is true, //! serial version and `Erased + Send + Sync` for the parallel version.
//! `RefCell` otherwise.
//! //!
//! `RwLock` is a read-write lock. //! Types
//! It internally uses `parking_lot::RwLock` if cfg!(parallel_compiler) is true, //! -----
//! `RefCell` otherwise. //! The parallel versions of types provide various kinds of synchronization,
//! while the serial compiler versions do not.
//! //!
//! `MTLock` is a mutex which disappears if cfg!(parallel_compiler) is false. //! The following table shows how the types are implemented internally. Except
//! where noted otherwise, the type in column one is defined as a
//! newtype around the type from column two or three.
//! //!
//! `MTRef` is an immutable reference if cfg!(parallel_compiler), and a mutable reference otherwise. //! | Type | Serial version | Parallel version |
//! | ----------------------- | ------------------- | ------------------------------- |
//! | `Lrc<T>` | `rc::Rc<T>` | `sync::Arc<T>` |
//! |` Weak<T>` | `rc::Weak<T>` | `sync::Weak<T>` |
//! | | | |
//! | `AtomicBool` | `Cell<bool>` | `atomic::AtomicBool` |
//! | `AtomicU32` | `Cell<u32>` | `atomic::AtomicU32` |
//! | `AtomicU64` | `Cell<u64>` | `atomic::AtomicU64` |
//! | `AtomicUsize` | `Cell<usize>` | `atomic::AtomicUsize` |
//! | | | |
//! | `Lock<T>` | `RefCell<T>` | `parking_lot::Mutex<T>` |
//! | `RwLock<T>` | `RefCell<T>` | `parking_lot::RwLock<T>` |
//! | `MTLock<T>` [^1] | `T` | `Lock<T>` |
//! | `MTLockRef<'a, T>` [^2] | `&'a mut MTLock<T>` | `&'a MTLock<T>` |
//! | | | |
//! | `ParallelIterator` | `Iterator` | `rayon::iter::ParallelIterator` |
//! //!
//! `rustc_erase_owner!` erases an OwningRef owner into Erased or Erased + Send + Sync //! [^1] `MTLock` is similar to `Lock`, but the serial version avoids the cost
//! depending on the value of cfg!(parallel_compiler). //! of a `RefCell`. This is appropriate when interior mutability is not
//! required.
//!
//! [^2] `MTLockRef` is a typedef.
use crate::owning_ref::{Erased, OwningRef}; use crate::owning_ref::{Erased, OwningRef};
use std::collections::HashMap; use std::collections::HashMap;
@ -209,7 +234,7 @@ cfg_if! {
} }
} }
pub type MTRef<'a, T> = &'a mut T; pub type MTLockRef<'a, T> = &'a mut MTLock<T>;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct MTLock<T>(T); pub struct MTLock<T>(T);
@ -267,7 +292,7 @@ cfg_if! {
pub use std::sync::Arc as Lrc; pub use std::sync::Arc as Lrc;
pub use std::sync::Weak as Weak; pub use std::sync::Weak as Weak;
pub type MTRef<'a, T> = &'a T; pub type MTLockRef<'a, T> = &'a MTLock<T>;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct MTLock<T>(Lock<T>); pub struct MTLock<T>(Lock<T>);

View file

@ -174,7 +174,7 @@
//! regardless of whether it is actually needed or not. //! regardless of whether it is actually needed or not.
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::{par_for_each_in, MTLock, MTRef}; use rustc_data_structures::sync::{par_for_each_in, MTLock, MTLockRef};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
@ -340,8 +340,8 @@ pub fn collect_crate_mono_items(
let recursion_limit = tcx.recursion_limit(); let recursion_limit = tcx.recursion_limit();
{ {
let visited: MTRef<'_, _> = &mut visited; let visited: MTLockRef<'_, _> = &mut visited;
let inlining_map: MTRef<'_, _> = &mut inlining_map; let inlining_map: MTLockRef<'_, _> = &mut inlining_map;
tcx.sess.time("monomorphization_collector_graph_walk", || { tcx.sess.time("monomorphization_collector_graph_walk", || {
par_for_each_in(roots, |root| { par_for_each_in(roots, |root| {
@ -406,10 +406,10 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
fn collect_items_rec<'tcx>( fn collect_items_rec<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
starting_point: Spanned<MonoItem<'tcx>>, starting_point: Spanned<MonoItem<'tcx>>,
visited: MTRef<'_, MTLock<FxHashSet<MonoItem<'tcx>>>>, visited: MTLockRef<'_, FxHashSet<MonoItem<'tcx>>>,
recursion_depths: &mut DefIdMap<usize>, recursion_depths: &mut DefIdMap<usize>,
recursion_limit: Limit, recursion_limit: Limit,
inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>, inlining_map: MTLockRef<'_, InliningMap<'tcx>>,
) { ) {
if !visited.lock_mut().insert(starting_point.node) { if !visited.lock_mut().insert(starting_point.node) {
// We've been here already, no need to search again. // We've been here already, no need to search again.