@@ -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 ! {
@@ -99,6 +103,25 @@ impl ThreadId {
99103 }
100104 }
101105
106+ /// Generates a new unique thread ID.
107+ pub ( crate ) fn new ( ) -> ThreadId {
108+ cfg_select ! {
109+ target_has_atomic = "64" => {
110+ // The generation is implemented lock-free anyway.
111+ ThreadId :: desperate_new( )
112+ }
113+ _ => {
114+ // Synchronize the id generation – `Mutex` has better
115+ // synchronization behaviour than the spinlock used in
116+ // `desperate_new`, but might need allocation.
117+ use crate :: sync:: nonpoison:: Mutex ;
118+ static LOCK : Mutex <( ) > = Mutex :: new( ( ) ) ;
119+ let _guard = LOCK . lock( ) ;
120+ ThreadId :: desperate_new( )
121+ }
122+ }
123+ }
124+
102125 #[ cfg( any( not( target_thread_local) , target_has_atomic = "64" ) ) ]
103126 pub ( super ) fn from_u64 ( v : u64 ) -> Option < ThreadId > {
104127 NonZero :: new ( v) . map ( ThreadId )
0 commit comments