Skip to content

Commit eb72733

Browse files
committed
refactor Lock again
1 parent d28b02b commit eb72733

File tree

2 files changed

+81
-50
lines changed

2 files changed

+81
-50
lines changed

compiler/rustc_data_structures/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#![feature(sync_unsafe_cell)]
3232
#![feature(const_trait_impl)]
3333
#![feature(const_mut_refs)]
34+
#![feature(const_ptr_as_ref)]
3435
#![allow(rustc::default_hash_types)]
3536
#![allow(rustc::potential_query_instability)]
3637
#![deny(rustc::untranslatable_diagnostic)]

compiler/rustc_data_structures/src/sync.rs

Lines changed: 80 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,13 @@
4343
//! [^2] `MTLockRef` is a typedef.
4444
4545
use crate::owning_ref::{Erased, OwningRef};
46-
use std::cell::{RefCell, RefMut};
46+
use std::cell::{Cell, UnsafeCell};
4747
use std::collections::HashMap;
48+
use std::fmt::{Debug, Formatter};
4849
use std::hash::{BuildHasher, Hash};
49-
use std::mem::{transmute, MaybeUninit};
50+
use std::intrinsics::likely;
51+
use std::marker::PhantomData;
52+
use std::mem::MaybeUninit;
5053
use std::ops::{Deref, DerefMut};
5154
use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
5255

@@ -56,8 +59,8 @@ pub use std::sync::atomic::Ordering::SeqCst;
5659
pub use vec::AppendOnlyVec;
5760

5861
mod vec;
59-
use std::sync::Mutex;
60-
use std::sync::MutexGuard;
62+
use parking_lot::lock_api::RawMutex as _;
63+
use parking_lot::RawMutex;
6164

6265
mod mode {
6366
use super::Ordering;
@@ -257,8 +260,6 @@ cfg_if! {
257260

258261
use std::cell::RefCell as InnerRwLock;
259262

260-
use std::cell::Cell;
261-
262263
pub type MTLockRef<'a, T> = &'a mut MTLock<T>;
263264

264265
#[derive(Debug, Default)]
@@ -588,77 +589,86 @@ impl<K: Eq + Hash, V: Eq, S: BuildHasher> HashMapExt<K, V> for HashMap<K, V, S>
588589
}
589590
}
590591

591-
#[derive(Debug)]
592592
pub struct Lock<T> {
593593
single_thread: bool,
594-
inner: RefCell<T>,
595-
mt_inner: Option<Mutex<T>>,
594+
data: UnsafeCell<T>,
595+
borrow: Cell<bool>,
596+
mutex: RawMutex,
597+
}
598+
599+
impl<T: Debug> Debug for Lock<T> {
600+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
601+
match self.try_lock() {
602+
Some(guard) => f.debug_struct("Lock").field("data", &&*guard).finish(),
603+
None => {
604+
struct LockedPlaceholder;
605+
impl Debug for LockedPlaceholder {
606+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
607+
f.write_str("<locked>")
608+
}
609+
}
610+
611+
f.debug_struct("Lock").field("data", &LockedPlaceholder).finish()
612+
}
613+
}
614+
}
596615
}
597616

598617
impl<T> Lock<T> {
599618
#[inline]
600619
pub fn new(val: T) -> Self {
601-
if !active() {
602-
Self { single_thread: true, inner: RefCell::new(val), mt_inner: None }
603-
} else {
604-
Self {
605-
single_thread: false,
606-
// SAFETY: `inner` will never be accessed in multiple thread
607-
inner: unsafe { MaybeUninit::zeroed().assume_init() },
608-
mt_inner: Some(Mutex::new(val)),
609-
}
620+
Lock {
621+
single_thread: !active(),
622+
data: UnsafeCell::new(val),
623+
borrow: Cell::new(false),
624+
mutex: RawMutex::INIT,
610625
}
611626
}
612627

613628
#[inline]
614629
pub fn into_inner(self) -> T {
615-
if self.single_thread {
616-
self.inner.into_inner()
617-
} else {
618-
self.mt_inner.unwrap().into_inner().unwrap()
619-
}
630+
self.data.into_inner()
620631
}
621632

622633
#[inline]
623634
pub fn get_mut(&mut self) -> &mut T {
624-
if self.single_thread {
625-
self.inner.get_mut()
626-
} else {
627-
// SAFETY: the `&mut T` is accessible as long as self exists.
628-
self.mt_inner.as_mut().unwrap().get_mut().unwrap()
629-
}
635+
self.data.get_mut()
630636
}
631637

632638
#[inline]
633639
pub fn try_lock(&self) -> Option<LockGuard<'_, T>> {
634640
// SAFETY: the `&mut T` is accessible as long as self exists.
635-
if self.single_thread {
636-
let mut r = self.inner.try_borrow_mut().ok()?;
637-
Some(LockGuard(unsafe { transmute(r.deref_mut()) }, Some(r), None))
641+
if likely(self.single_thread) {
642+
if self.borrow.get() {
643+
None
644+
} else {
645+
self.borrow.set(true);
646+
Some(LockGuard { lock: &self, marker: PhantomData })
647+
}
638648
} else {
639-
let mut l = self.mt_inner.as_ref().unwrap().try_lock().ok()?;
640-
Some(LockGuard(unsafe { transmute(l.deref_mut()) }, None, Some(l)))
649+
if !self.mutex.try_lock() {
650+
None
651+
} else {
652+
Some(LockGuard { lock: &self, marker: PhantomData })
653+
}
641654
}
642655
}
643656

644-
fn mt_lock(&self) -> MutexGuard<'_, T> {
645-
self.mt_inner.as_ref().unwrap().lock().unwrap_or_else(|e| {
646-
self.mt_inner.as_ref().unwrap().clear_poison();
647-
e.into_inner()
648-
})
657+
#[inline(never)]
658+
fn lock_raw(&self) {
659+
if likely(self.single_thread) {
660+
assert!(!self.borrow.get());
661+
self.borrow.set(true);
662+
} else {
663+
self.mutex.lock();
664+
}
649665
}
650666

651667
#[inline(always)]
652668
#[track_caller]
653669
pub fn lock(&self) -> LockGuard<'_, T> {
654-
// SAFETY: the `&mut T` is accessible as long as self exists.
655-
if self.single_thread {
656-
let mut r = self.inner.borrow_mut();
657-
LockGuard(unsafe { transmute(r.deref_mut()) }, Some(r), None)
658-
} else {
659-
let mut l = self.mt_lock();
660-
LockGuard(unsafe { transmute(l.deref_mut()) }, None, Some(l))
661-
}
670+
self.lock_raw();
671+
LockGuard { lock: &self, marker: PhantomData }
662672
}
663673

664674
#[inline(always)]
@@ -699,19 +709,39 @@ impl<T: Clone> Clone for Lock<T> {
699709
unsafe impl<T: Send> std::marker::Send for Lock<T> {}
700710
unsafe impl<T: Send> std::marker::Sync for Lock<T> {}
701711

702-
pub struct LockGuard<'a, T>(&'a mut T, Option<RefMut<'a, T>>, Option<MutexGuard<'a, T>>);
712+
pub struct LockGuard<'a, T> {
713+
lock: &'a Lock<T>,
714+
marker: PhantomData<&'a mut T>,
715+
}
703716

704717
impl<T> const Deref for LockGuard<'_, T> {
705718
type Target = T;
706719

707720
fn deref(&self) -> &T {
708-
self.0
721+
unsafe { &*self.lock.data.get() }
709722
}
710723
}
711724

712725
impl<T> const DerefMut for LockGuard<'_, T> {
713726
fn deref_mut(&mut self) -> &mut T {
714-
self.0
727+
unsafe { &mut *self.lock.data.get() }
728+
}
729+
}
730+
731+
#[inline(never)]
732+
unsafe fn unlock_mt<T>(guard: &mut LockGuard<'_, T>) {
733+
guard.lock.mutex.unlock()
734+
}
735+
736+
impl<'a, T> Drop for LockGuard<'a, T> {
737+
#[inline]
738+
fn drop(&mut self) {
739+
if likely(self.lock.single_thread) {
740+
debug_assert!(self.lock.borrow.get());
741+
self.lock.borrow.set(false);
742+
} else {
743+
unsafe { unlock_mt(self) }
744+
}
715745
}
716746
}
717747

0 commit comments

Comments
 (0)