159
159
mod tests;
160
160
161
161
use crate :: any:: Any ;
162
+ use crate :: cell:: SyncUnsafeCell ;
162
163
use crate :: cell:: { OnceCell , UnsafeCell } ;
163
164
use crate :: env;
164
165
use crate :: ffi:: { CStr , CString } ;
165
166
use crate :: fmt;
166
167
use crate :: io;
167
168
use crate :: marker:: PhantomData ;
169
+ use crate :: mem:: MaybeUninit ;
168
170
use crate :: mem:: { self , forget} ;
169
171
use crate :: num:: NonZero ;
170
172
use crate :: panic;
@@ -530,7 +532,7 @@ impl Builder {
530
532
531
533
let f = MaybeDangling :: new ( f) ;
532
534
let main = move || {
533
- if let Some ( name) = their_thread. cname ( ) {
535
+ if let Some ( name) = their_thread. 0 . name ( ) {
534
536
imp:: Thread :: set_name ( name) ;
535
537
}
536
538
@@ -1162,7 +1164,7 @@ pub fn park_timeout(dur: Duration) {
1162
1164
let guard = PanicGuard ;
1163
1165
// SAFETY: park_timeout is called on the parker owned by this thread.
1164
1166
unsafe {
1165
- current ( ) . inner . as_ref ( ) . parker ( ) . park_timeout ( dur) ;
1167
+ current ( ) . 0 . parker ( ) . park_timeout ( dur) ;
1166
1168
}
1167
1169
// No panic occurred, do not abort.
1168
1170
forget ( guard) ;
@@ -1201,7 +1203,12 @@ pub fn park_timeout(dur: Duration) {
1201
1203
pub struct ThreadId ( NonZero < u64 > ) ;
1202
1204
1203
1205
impl ThreadId {
1204
- // Generate a new unique thread ID.
1206
+ /// Generate a new unique thread ID.
1207
+ ///
1208
+ /// The current implementation starts at 2 and increments from there.
1209
+ ///
1210
+ /// This is as `1` is the value for the main thread, so std::thread::Thread does not
1211
+ /// have to store this value when creating the main thread's information.
1205
1212
fn new ( ) -> ThreadId {
1206
1213
#[ cold]
1207
1214
fn exhausted ( ) -> ! {
@@ -1212,7 +1219,7 @@ impl ThreadId {
1212
1219
if #[ cfg( target_has_atomic = "64" ) ] {
1213
1220
use crate :: sync:: atomic:: AtomicU64 ;
1214
1221
1215
- static COUNTER : AtomicU64 = AtomicU64 :: new( 0 ) ;
1222
+ static COUNTER : AtomicU64 = AtomicU64 :: new( 1 ) ;
1216
1223
1217
1224
let mut last = COUNTER . load( Ordering :: Relaxed ) ;
1218
1225
loop {
@@ -1228,7 +1235,7 @@ impl ThreadId {
1228
1235
} else {
1229
1236
use crate :: sync:: { Mutex , PoisonError } ;
1230
1237
1231
- static COUNTER : Mutex <u64 > = Mutex :: new( 0 ) ;
1238
+ static COUNTER : Mutex <u64 > = Mutex :: new( 1 ) ;
1232
1239
1233
1240
let mut counter = COUNTER . lock( ) . unwrap_or_else( PoisonError :: into_inner) ;
1234
1241
let Some ( id) = counter. checked_add( 1 ) else {
@@ -1245,6 +1252,11 @@ impl ThreadId {
1245
1252
}
1246
1253
}
1247
1254
1255
+ /// Creates a ThreadId with the ID of the main thread.
1256
+ fn new_main ( ) -> Self {
1257
+ Self ( NonZero :: < u64 > :: MIN )
1258
+ }
1259
+
1248
1260
/// This returns a numeric identifier for the thread identified by this
1249
1261
/// `ThreadId`.
1250
1262
///
@@ -1264,23 +1276,59 @@ impl ThreadId {
1264
1276
// Thread
1265
1277
////////////////////////////////////////////////////////////////////////////////
1266
1278
1267
- /// The internal representation of a `Thread`'s name.
1268
- enum ThreadName {
1269
- Main ,
1270
- Other ( CString ) ,
1271
- Unnamed ,
1272
- }
1279
+ /// The parker for the main thread. This avoids having to allocate an Arc in `fn main() {}`.
1280
+ static MAIN_PARKER : SyncUnsafeCell < MaybeUninit < Parker > > =
1281
+ SyncUnsafeCell :: new ( MaybeUninit :: uninit ( ) ) ;
1273
1282
1274
- /// The internal representation of a `Thread` handle
1275
- struct Inner {
1276
- name : ThreadName , // Guaranteed to be UTF-8
1283
+ /// The internal representation of a `Thread` that is not the main thread.
1284
+ struct OtherInner {
1285
+ name : Option < CString > , // Guaranteed to be UTF-8
1277
1286
id : ThreadId ,
1278
1287
parker : Parker ,
1279
1288
}
1280
1289
1290
+ /// The internal representation of a `Thread` handle.
1291
+ #[ derive( Clone ) ]
1292
+ enum Inner {
1293
+ /// Represents the main thread. May only be constructed by Thread::new_main.
1294
+ Main ,
1295
+ /// Represents any other thread.
1296
+ Other ( Pin < Arc < OtherInner > > ) ,
1297
+ }
1298
+
1281
1299
impl Inner {
1282
- fn parker ( self : Pin < & Self > ) -> Pin < & Parker > {
1283
- unsafe { Pin :: map_unchecked ( self , |inner| & inner. parker ) }
1300
+ fn id ( & self ) -> ThreadId {
1301
+ match self {
1302
+ Self :: Main => ThreadId :: new_main ( ) ,
1303
+ Self :: Other ( other) => other. id ,
1304
+ }
1305
+ }
1306
+
1307
+ fn name ( & self ) -> Option < & CStr > {
1308
+ match self {
1309
+ Self :: Main => Some ( c"main" ) ,
1310
+ Self :: Other ( other) => other. name . as_deref ( ) ,
1311
+ }
1312
+ }
1313
+
1314
+ fn parker ( & self ) -> Pin < & Parker > {
1315
+ match self {
1316
+ Self :: Main => {
1317
+ // Safety: MAIN_PARKER is only ever read in this function, which requires access
1318
+ // to an existing `&Inner` value, which can only be accessed via the main thread
1319
+ // giving away such an instance from `current()`, implying that initialization,
1320
+ // the only write to `MAIN_PARKER`, has been completed.
1321
+ let static_ref: & ' static MaybeUninit < Parker > = unsafe { & * MAIN_PARKER . get ( ) } ;
1322
+
1323
+ // Safety: MAIN_PARKER is initialised when Inner::Main is initialised.
1324
+ let parker_ref = unsafe { static_ref. assume_init_ref ( ) } ;
1325
+
1326
+ Pin :: static_ref ( parker_ref)
1327
+ }
1328
+ Self :: Other ( inner) => unsafe {
1329
+ Pin :: map_unchecked ( inner. as_ref ( ) , |inner| & inner. parker )
1330
+ } ,
1331
+ }
1284
1332
}
1285
1333
}
1286
1334
@@ -1304,46 +1352,56 @@ impl Inner {
1304
1352
/// docs of [`Builder`] and [`spawn`] for more details.
1305
1353
///
1306
1354
/// [`thread::current`]: current
1307
- pub struct Thread {
1308
- inner : Pin < Arc < Inner > > ,
1309
- }
1355
+ pub struct Thread ( Inner ) ;
1310
1356
1311
1357
impl Thread {
1312
1358
/// Used only internally to construct a thread object without spawning.
1313
1359
///
1314
1360
/// # Safety
1315
1361
/// `name` must be valid UTF-8.
1316
1362
pub ( crate ) unsafe fn new ( name : CString ) -> Thread {
1317
- unsafe { Self :: new_inner ( ThreadName :: Other ( name) ) }
1363
+ unsafe { Self :: new_inner ( Some ( name) ) }
1318
1364
}
1319
1365
1320
1366
pub ( crate ) fn new_unnamed ( ) -> Thread {
1321
- unsafe { Self :: new_inner ( ThreadName :: Unnamed ) }
1367
+ unsafe { Self :: new_inner ( None ) }
1322
1368
}
1323
1369
1324
- // Used in runtime to construct main thread
1325
- pub ( crate ) fn new_main ( ) -> Thread {
1326
- unsafe { Self :: new_inner ( ThreadName :: Main ) }
1370
+ /// Used in runtime to construct main thread
1371
+ ///
1372
+ /// # Safety
1373
+ ///
1374
+ /// This must only ever be called once, and must be called on the main thread.
1375
+ pub ( crate ) unsafe fn new_main ( ) -> Thread {
1376
+ // Safety: As this is only called once and on the main thread, nothing else is accessing MAIN_PARKER
1377
+ // as the only other read occurs in Inner::parker *after* Inner::Main has been constructed,
1378
+ // and this function is the only one that constructs Inner::Main.
1379
+ //
1380
+ // Pre-main thread spawning cannot hit this either, as the caller promises that this is only called on the main thread.
1381
+ unsafe { Parker :: new_in_place ( MAIN_PARKER . get ( ) . cast ( ) ) }
1382
+
1383
+ Self ( Inner :: Main )
1327
1384
}
1328
1385
1329
1386
/// # Safety
1330
- /// If `name` is `ThreadName::Other(_)`, the contained string must be valid UTF-8.
1331
- unsafe fn new_inner ( name : ThreadName ) -> Thread {
1387
+ ///
1388
+ /// If `name` is `Some(_)`, the contained string must be valid UTF-8.
1389
+ unsafe fn new_inner ( name : Option < CString > ) -> Thread {
1332
1390
// We have to use `unsafe` here to construct the `Parker` in-place,
1333
1391
// which is required for the UNIX implementation.
1334
1392
//
1335
1393
// SAFETY: We pin the Arc immediately after creation, so its address never
1336
1394
// changes.
1337
1395
let inner = unsafe {
1338
- let mut arc = Arc :: < Inner > :: new_uninit ( ) ;
1396
+ let mut arc = Arc :: < OtherInner > :: new_uninit ( ) ;
1339
1397
let ptr = Arc :: get_mut_unchecked ( & mut arc) . as_mut_ptr ( ) ;
1340
1398
addr_of_mut ! ( ( * ptr) . name) . write ( name) ;
1341
1399
addr_of_mut ! ( ( * ptr) . id) . write ( ThreadId :: new ( ) ) ;
1342
1400
Parker :: new_in_place ( addr_of_mut ! ( ( * ptr) . parker) ) ;
1343
1401
Pin :: new_unchecked ( arc. assume_init ( ) )
1344
1402
} ;
1345
1403
1346
- Thread { inner }
1404
+ Self ( Inner :: Other ( inner) )
1347
1405
}
1348
1406
1349
1407
/// Like the public [`park`], but callable on any handle. This is used to
@@ -1352,7 +1410,7 @@ impl Thread {
1352
1410
/// # Safety
1353
1411
/// May only be called from the thread to which this handle belongs.
1354
1412
pub ( crate ) unsafe fn park ( & self ) {
1355
- unsafe { self . inner . as_ref ( ) . parker ( ) . park ( ) }
1413
+ unsafe { self . 0 . parker ( ) . park ( ) }
1356
1414
}
1357
1415
1358
1416
/// Atomically makes the handle's token available if it is not already.
@@ -1388,7 +1446,7 @@ impl Thread {
1388
1446
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1389
1447
#[ inline]
1390
1448
pub fn unpark ( & self ) {
1391
- self . inner . as_ref ( ) . parker ( ) . unpark ( ) ;
1449
+ self . 0 . parker ( ) . unpark ( ) ;
1392
1450
}
1393
1451
1394
1452
/// Gets the thread's unique identifier.
@@ -1408,7 +1466,7 @@ impl Thread {
1408
1466
#[ stable( feature = "thread_id" , since = "1.19.0" ) ]
1409
1467
#[ must_use]
1410
1468
pub fn id ( & self ) -> ThreadId {
1411
- self . inner . id
1469
+ self . 0 . id ( )
1412
1470
}
1413
1471
1414
1472
/// Gets the thread's name.
@@ -1451,15 +1509,7 @@ impl Thread {
1451
1509
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1452
1510
#[ must_use]
1453
1511
pub fn name ( & self ) -> Option < & str > {
1454
- self . cname ( ) . map ( |s| unsafe { str:: from_utf8_unchecked ( s. to_bytes ( ) ) } )
1455
- }
1456
-
1457
- fn cname ( & self ) -> Option < & CStr > {
1458
- match & self . inner . name {
1459
- ThreadName :: Main => Some ( c"main" ) ,
1460
- ThreadName :: Other ( other) => Some ( & other) ,
1461
- ThreadName :: Unnamed => None ,
1462
- }
1512
+ self . 0 . name ( ) . map ( |s| unsafe { str:: from_utf8_unchecked ( s. to_bytes ( ) ) } )
1463
1513
}
1464
1514
}
1465
1515
0 commit comments