@@ -34,7 +34,9 @@ pub use self::atomic::AtomicU64;
3434pub use self :: freeze:: { FreezeLock , FreezeReadGuard , FreezeWriteGuard } ;
3535#[ doc( no_inline) ]
3636pub use self :: lock:: { Lock , LockGuard , Mode } ;
37- pub use self :: mode:: { is_dyn_thread_safe, set_dyn_thread_safe_mode} ;
37+ pub use self :: mode:: {
38+ FromDyn , check_dyn_thread_safe, is_dyn_thread_safe, set_dyn_thread_safe_mode,
39+ } ;
3840pub use self :: parallel:: {
3941 broadcast, par_fns, par_for_each_in, par_join, par_map, parallel_guard, spawn,
4042 try_par_for_each_in,
@@ -64,12 +66,20 @@ mod atomic {
6466mod mode {
6567 use std:: sync:: atomic:: { AtomicU8 , Ordering } ;
6668
69+ use crate :: sync:: { DynSend , DynSync } ;
70+
6771 const UNINITIALIZED : u8 = 0 ;
6872 const DYN_NOT_THREAD_SAFE : u8 = 1 ;
6973 const DYN_THREAD_SAFE : u8 = 2 ;
7074
7175 static DYN_THREAD_SAFE_MODE : AtomicU8 = AtomicU8 :: new ( UNINITIALIZED ) ;
7276
77+ // Whether thread safety is enabled (due to running under multiple threads).
78+ #[ inline]
79+ pub fn check_dyn_thread_safe ( ) -> Option < FromDyn < ( ) > > {
80+ is_dyn_thread_safe ( ) . then_some ( FromDyn ( ( ) ) )
81+ }
82+
7383 // Whether thread safety is enabled (due to running under multiple threads).
7484 #[ inline]
7585 pub fn is_dyn_thread_safe ( ) -> bool {
@@ -99,6 +109,44 @@ mod mode {
99109 // Check that the mode was either uninitialized or was already set to the requested mode.
100110 assert ! ( previous. is_ok( ) || previous == Err ( set) ) ;
101111 }
112+
113+ #[ derive( Copy , Clone ) ]
114+ pub struct FromDyn < T > ( T ) ;
115+
116+ impl < T > FromDyn < T > {
117+ #[ inline( always) ]
118+ pub fn derive < O > ( & self , val : O ) -> FromDyn < O > {
119+ // We already did the check for `sync::is_dyn_thread_safe()` when creating `Self`
120+ FromDyn ( val)
121+ }
122+
123+ #[ inline( always) ]
124+ pub fn into_inner ( self ) -> T {
125+ self . 0
126+ }
127+ }
128+
129+ // `FromDyn` is `Send` if `T` is `DynSend`, since it ensures that sync::is_dyn_thread_safe() is true.
130+ unsafe impl < T : DynSend > Send for FromDyn < T > { }
131+
132+ // `FromDyn` is `Sync` if `T` is `DynSync`, since it ensures that sync::is_dyn_thread_safe() is true.
133+ unsafe impl < T : DynSync > Sync for FromDyn < T > { }
134+
135+ impl < T > std:: ops:: Deref for FromDyn < T > {
136+ type Target = T ;
137+
138+ #[ inline( always) ]
139+ fn deref ( & self ) -> & Self :: Target {
140+ & self . 0
141+ }
142+ }
143+
144+ impl < T > std:: ops:: DerefMut for FromDyn < T > {
145+ #[ inline( always) ]
146+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
147+ & mut self . 0
148+ }
149+ }
102150}
103151
104152/// This makes locks panic if they are already held.
0 commit comments