43
43
//! [^2] `MTLockRef` is a typedef.
44
44
45
45
use crate :: owning_ref:: { Erased , OwningRef } ;
46
- use std:: cell:: { RefCell , RefMut } ;
46
+ use std:: cell:: { Cell , UnsafeCell } ;
47
47
use std:: collections:: HashMap ;
48
+ use std:: fmt:: { Debug , Formatter } ;
48
49
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 ;
50
53
use std:: ops:: { Deref , DerefMut } ;
51
54
use std:: panic:: { catch_unwind, resume_unwind, AssertUnwindSafe } ;
52
55
@@ -56,8 +59,8 @@ pub use std::sync::atomic::Ordering::SeqCst;
56
59
pub use vec:: AppendOnlyVec ;
57
60
58
61
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 ;
61
64
62
65
mod mode {
63
66
use super :: Ordering ;
@@ -257,8 +260,6 @@ cfg_if! {
257
260
258
261
use std:: cell:: RefCell as InnerRwLock ;
259
262
260
- use std:: cell:: Cell ;
261
-
262
263
pub type MTLockRef <' a, T > = & ' a mut MTLock <T >;
263
264
264
265
#[ derive( Debug , Default ) ]
@@ -588,77 +589,86 @@ impl<K: Eq + Hash, V: Eq, S: BuildHasher> HashMapExt<K, V> for HashMap<K, V, S>
588
589
}
589
590
}
590
591
591
- #[ derive( Debug ) ]
592
592
pub struct Lock < T > {
593
593
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
+ }
596
615
}
597
616
598
617
impl < T > Lock < T > {
599
618
#[ inline]
600
619
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 ,
610
625
}
611
626
}
612
627
613
628
#[ inline]
614
629
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 ( )
620
631
}
621
632
622
633
#[ inline]
623
634
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 ( )
630
636
}
631
637
632
638
#[ inline]
633
639
pub fn try_lock ( & self ) -> Option < LockGuard < ' _ , T > > {
634
640
// 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
+ }
638
648
} 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
+ }
641
654
}
642
655
}
643
656
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
+ }
649
665
}
650
666
651
667
#[ inline( always) ]
652
668
#[ track_caller]
653
669
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 }
662
672
}
663
673
664
674
#[ inline( always) ]
@@ -699,19 +709,39 @@ impl<T: Clone> Clone for Lock<T> {
699
709
unsafe impl < T : Send > std:: marker:: Send for Lock < T > { }
700
710
unsafe impl < T : Send > std:: marker:: Sync for Lock < T > { }
701
711
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
+ }
703
716
704
717
impl < T > const Deref for LockGuard < ' _ , T > {
705
718
type Target = T ;
706
719
707
720
fn deref ( & self ) -> & T {
708
- self . 0
721
+ unsafe { & * self . lock . data . get ( ) }
709
722
}
710
723
}
711
724
712
725
impl < T > const DerefMut for LockGuard < ' _ , T > {
713
726
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
+ }
715
745
}
716
746
}
717
747
0 commit comments