@@ -31,11 +31,15 @@ use crate::sync::atomic::{Atomic, Ordering};
3131pub struct ThreadId ( NonZero < u64 > ) ;
3232
3333impl ThreadId {
34- // Generate a new unique thread ID.
35- pub ( crate ) fn new ( ) -> ThreadId {
34+ /// Generates a new unique thread ID, and does not rely on the global
35+ /// allocator.
36+ ///
37+ /// This should only be used in contexts where a new `ThreadId` is
38+ /// desperately required, but the global allocator might not be available.
39+ pub ( super ) fn desperate_new ( ) -> ThreadId {
3640 #[ cold]
3741 fn exhausted ( ) -> ! {
38- panic ! ( "failed to generate unique thread ID: bitspace exhausted" )
42+ rtabort ! ( "failed to generate unique thread ID: bitspace exhausted" )
3943 }
4044
4145 cfg_select ! {
@@ -96,6 +100,25 @@ impl ThreadId {
96100 }
97101 }
98102
103+ /// Generates a new unique thread ID.
104+ pub ( crate ) fn new ( ) -> ThreadId {
105+ cfg_select ! {
106+ target_has_atomic = "64" => {
107+ // The generation is implemented lock-free anyway.
108+ ThreadId :: desperate_new( )
109+ }
110+ _ => {
111+ // Synchronize the id generation – `Mutex` has better
112+ // synchronization behaviour than the spinlock used in
113+ // `desperate_new`, but might need allocation.
114+ use crate :: sync:: nonpoison:: Mutex ;
115+ static LOCK : Mutex <( ) > = Mutex :: new( ( ) ) ;
116+ let _guard = LOCK . lock( ) ;
117+ ThreadId :: desperate_new( )
118+ }
119+ }
120+ }
121+
99122 #[ cfg( any( not( target_thread_local) , target_has_atomic = "64" ) ) ]
100123 pub ( super ) fn from_u64 ( v : u64 ) -> Option < ThreadId > {
101124 NonZero :: new ( v) . map ( ThreadId )
0 commit comments