@@ -359,7 +359,10 @@ mod state {
359
359
use crate :: loom:: sync:: atomic:: AtomicUsize ;
360
360
use crate :: loom:: sync:: atomic:: Ordering :: SeqCst ;
361
361
362
- const CLOSED : usize = 1 ;
362
+ const CLOSED_BIT : usize = 1 ;
363
+
364
+ // Using 2 as the step size preserves the the `CLOSED_BIT`.
365
+ const STEP_SIZE : usize = 2 ;
363
366
364
367
/// The version part of the state. The lowest bit is always zero.
365
368
#[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
@@ -378,39 +381,34 @@ mod state {
378
381
pub ( super ) struct AtomicState ( AtomicUsize ) ;
379
382
380
383
impl Version {
381
- /// Get the initial version when creating the channel.
382
- pub ( super ) fn initial ( ) -> Self {
383
- // The initial version is 1 so that `mark_changed` can decrement by one.
384
- // (The value is 2 due to the closed bit.)
385
- Version ( 2 )
386
- }
387
-
388
384
/// Decrements the version.
389
385
pub ( super ) fn decrement ( & mut self ) {
390
- // Decrement by two to avoid touching the CLOSED bit.
391
- if self . 0 >= 2 {
392
- self . 0 -= 2 ;
393
- }
386
+ // Using a wrapping decrement here is required to ensure that the
387
+ // operation is consistent with `std::sync::atomic::AtomicUsize::fetch_add()`
388
+ // which wraps on overflow.
389
+ self . 0 = self . 0 . wrapping_sub ( STEP_SIZE ) ;
394
390
}
391
+
392
+ pub ( super ) const INITIAL : Self = Version ( 0 ) ;
395
393
}
396
394
397
395
impl StateSnapshot {
398
396
/// Extract the version from the state.
399
397
pub ( super ) fn version ( self ) -> Version {
400
- Version ( self . 0 & !CLOSED )
398
+ Version ( self . 0 & !CLOSED_BIT )
401
399
}
402
400
403
401
/// Is the closed bit set?
404
402
pub ( super ) fn is_closed ( self ) -> bool {
405
- ( self . 0 & CLOSED ) == CLOSED
403
+ ( self . 0 & CLOSED_BIT ) == CLOSED_BIT
406
404
}
407
405
}
408
406
409
407
impl AtomicState {
410
408
/// Create a new `AtomicState` that is not closed and which has the
411
409
/// version set to `Version::initial()`.
412
410
pub ( super ) fn new ( ) -> Self {
413
- AtomicState ( AtomicUsize :: new ( 2 ) )
411
+ AtomicState ( AtomicUsize :: new ( Version :: INITIAL . 0 ) )
414
412
}
415
413
416
414
/// Load the current value of the state.
@@ -420,13 +418,12 @@ mod state {
420
418
421
419
/// Increment the version counter.
422
420
pub ( super ) fn increment_version ( & self ) {
423
- // Increment by two to avoid touching the CLOSED bit.
424
- self . 0 . fetch_add ( 2 , SeqCst ) ;
421
+ self . 0 . fetch_add ( STEP_SIZE , SeqCst ) ;
425
422
}
426
423
427
424
/// Set the closed bit in the state.
428
425
pub ( super ) fn set_closed ( & self ) {
429
- self . 0 . fetch_or ( CLOSED , SeqCst ) ;
426
+ self . 0 . fetch_or ( CLOSED_BIT , SeqCst ) ;
430
427
}
431
428
}
432
429
}
@@ -482,7 +479,7 @@ pub fn channel<T>(init: T) -> (Sender<T>, Receiver<T>) {
482
479
483
480
let rx = Receiver {
484
481
shared,
485
- version : Version :: initial ( ) ,
482
+ version : Version :: INITIAL ,
486
483
} ;
487
484
488
485
( tx, rx)
0 commit comments