@@ -32,14 +32,17 @@ use crate::{archetype::ArchetypeId, storage::SparseSetIndex};
3232use std:: { convert:: TryFrom , fmt, mem, sync:: atomic:: Ordering } ;
3333
3434#[ cfg( target_has_atomic = "64" ) ]
35- use std:: sync:: atomic:: AtomicI64 as AtomicInt ;
35+ use std:: sync:: atomic:: AtomicI64 as AtomicIdCursor ;
3636#[ cfg( target_has_atomic = "64" ) ]
37- type Int = i64 ;
37+ type IdCursor = i64 ;
3838
39+ /// Most modern platforms support 64-bit atomics, but some less-common platforms
40+ /// do not. This fallback allows compilation using a 32-bit cursor instead, with
41+ /// the caveat that some conversions may fail (and panic) at runtime.
3942#[ cfg( not( target_has_atomic = "64" ) ) ]
40- use std:: sync:: atomic:: AtomicI32 as AtomicInt ;
43+ use std:: sync:: atomic:: AtomicIsize as AtomicIdCursor ;
4144#[ cfg( not( target_has_atomic = "64" ) ) ]
42- type Int = i32 ;
45+ type IdCursor = isize ;
4346
4447/// Lightweight unique ID of an entity.
4548///
@@ -243,7 +246,7 @@ pub struct Entities {
243246 ///
244247 /// Once `flush()` is done, `free_cursor` will equal `pending.len()`.
245248 pending : Vec < u32 > ,
246- free_cursor : AtomicInt ,
249+ free_cursor : AtomicIdCursor ,
247250 /// Stores the number of free entities for [`len`](Entities::len)
248251 len : u32 ,
249252}
@@ -256,8 +259,12 @@ impl Entities {
256259 // Use one atomic subtract to grab a range of new IDs. The range might be
257260 // entirely nonnegative, meaning all IDs come from the freelist, or entirely
258261 // negative, meaning they are all new IDs to allocate, or a mix of both.
259- let range_end = self . free_cursor . fetch_sub ( count as Int , Ordering :: Relaxed ) ;
260- let range_start = range_end - count as Int ;
262+ let range_end = self
263+ . free_cursor
264+ // Unwrap: these conversions can only fail on platforms that don't support 64-bit atomics
265+ // and use AtomicIsize instead (see note on `IdCursor`).
266+ . fetch_sub ( IdCursor :: try_from ( count) . unwrap ( ) , Ordering :: Relaxed ) ;
267+ let range_start = range_end - IdCursor :: try_from ( count) . unwrap ( ) ;
261268
262269 let freelist_range = range_start. max ( 0 ) as usize ..range_end. max ( 0 ) as usize ;
263270
@@ -274,7 +281,7 @@ impl Entities {
274281 // In this example, we truncate the end to 0, leaving us with `-3..0`.
275282 // Then we negate these values to indicate how far beyond the end of `meta.end()`
276283 // to go, yielding `meta.len()+0 .. meta.len()+3`.
277- let base = self . meta . len ( ) as Int ;
284+ let base = self . meta . len ( ) as IdCursor ;
278285
279286 let new_id_end = u32:: try_from ( base - range_start) . expect ( "too many entities" ) ;
280287
@@ -311,7 +318,7 @@ impl Entities {
311318 // and farther beyond `meta.len()`.
312319 Entity {
313320 generation : 0 ,
314- id : u32:: try_from ( self . meta . len ( ) as Int - n) . expect ( "too many entities" ) ,
321+ id : u32:: try_from ( self . meta . len ( ) as IdCursor - n) . expect ( "too many entities" ) ,
315322 }
316323 }
317324 }
@@ -329,7 +336,7 @@ impl Entities {
329336 self . verify_flushed ( ) ;
330337 self . len += 1 ;
331338 if let Some ( id) = self . pending . pop ( ) {
332- let new_free_cursor = self . pending . len ( ) as Int ;
339+ let new_free_cursor = self . pending . len ( ) as IdCursor ;
333340 * self . free_cursor . get_mut ( ) = new_free_cursor;
334341 Entity {
335342 generation : self . meta [ id as usize ] . generation ,
@@ -351,14 +358,14 @@ impl Entities {
351358
352359 let loc = if entity. id as usize >= self . meta . len ( ) {
353360 self . pending . extend ( ( self . meta . len ( ) as u32 ) ..entity. id ) ;
354- let new_free_cursor = self . pending . len ( ) as Int ;
361+ let new_free_cursor = self . pending . len ( ) as IdCursor ;
355362 * self . free_cursor . get_mut ( ) = new_free_cursor;
356363 self . meta . resize ( entity. id as usize + 1 , EntityMeta :: EMPTY ) ;
357364 self . len += 1 ;
358365 None
359366 } else if let Some ( index) = self . pending . iter ( ) . position ( |item| * item == entity. id ) {
360367 self . pending . swap_remove ( index) ;
361- let new_free_cursor = self . pending . len ( ) as Int ;
368+ let new_free_cursor = self . pending . len ( ) as IdCursor ;
362369 * self . free_cursor . get_mut ( ) = new_free_cursor;
363370 self . len += 1 ;
364371 None
@@ -382,14 +389,14 @@ impl Entities {
382389
383390 let result = if entity. id as usize >= self . meta . len ( ) {
384391 self . pending . extend ( ( self . meta . len ( ) as u32 ) ..entity. id ) ;
385- let new_free_cursor = self . pending . len ( ) as Int ;
392+ let new_free_cursor = self . pending . len ( ) as IdCursor ;
386393 * self . free_cursor . get_mut ( ) = new_free_cursor;
387394 self . meta . resize ( entity. id as usize + 1 , EntityMeta :: EMPTY ) ;
388395 self . len += 1 ;
389396 AllocAtWithoutReplacement :: DidNotExist
390397 } else if let Some ( index) = self . pending . iter ( ) . position ( |item| * item == entity. id ) {
391398 self . pending . swap_remove ( index) ;
392- let new_free_cursor = self . pending . len ( ) as Int ;
399+ let new_free_cursor = self . pending . len ( ) as IdCursor ;
393400 * self . free_cursor . get_mut ( ) = new_free_cursor;
394401 self . len += 1 ;
395402 AllocAtWithoutReplacement :: DidNotExist
@@ -424,7 +431,7 @@ impl Entities {
424431
425432 self . pending . push ( entity. id ) ;
426433
427- let new_free_cursor = self . pending . len ( ) as Int ;
434+ let new_free_cursor = self . pending . len ( ) as IdCursor ;
428435 * self . free_cursor . get_mut ( ) = new_free_cursor;
429436 self . len -= 1 ;
430437 Some ( loc)
@@ -435,7 +442,9 @@ impl Entities {
435442 self . verify_flushed ( ) ;
436443
437444 let freelist_size = * self . free_cursor . get_mut ( ) ;
438- let shortfall = additional as Int - freelist_size;
445+ // Unwrap: these conversions can only fail on platforms that don't support 64-bit atomics
446+ // and use AtomicIsize instead (see note on `IdCursor`).
447+ let shortfall = IdCursor :: try_from ( additional) . unwrap ( ) - freelist_size;
439448 if shortfall > 0 {
440449 self . meta . reserve ( shortfall as usize ) ;
441450 }
@@ -492,7 +501,7 @@ impl Entities {
492501 }
493502
494503 fn needs_flush ( & mut self ) -> bool {
495- * self . free_cursor . get_mut ( ) != self . pending . len ( ) as Int
504+ * self . free_cursor . get_mut ( ) != self . pending . len ( ) as IdCursor
496505 }
497506
498507 /// Allocates space for entities previously reserved with `reserve_entity` or
0 commit comments