File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -484,11 +484,21 @@ impl RawIter {
484484
485485 fn size_hint < T : Send > ( & self , thread_local : & ThreadLocal < T > ) -> ( usize , Option < usize > ) {
486486 let total = thread_local. values . load ( Ordering :: Relaxed ) ;
487- ( total - self . yielded , None )
487+
488+ // NOTE: `saturating_sub` is required here to avoid integer underflow during
489+ // concurrent insertion and iteration. The shortest dangerous interleaving is:
490+ //
491+ // - Thread A inserts, pausing after `present = true` but *before* `values = 1`
492+ // - Thread B iterates, sees `present = true`, and sets `yielded = 1`
493+ // - Thread B calls `size_hint` and sees `values = 0` and `yielded = 1`
494+ ( total. saturating_sub ( self . yielded ) , None )
488495 }
489496
490497 fn size_hint_frozen < T : Send > ( & self , thread_local : & ThreadLocal < T > ) -> ( usize , Option < usize > ) {
491498 let total = thread_local. values . load ( Ordering :: Relaxed ) ;
499+
500+ // NOTE: this method assumes no concurrent insertion to `thread_local`,
501+ // so this subtraction cannot underflow as in `size_hint` above.
492502 let remaining = total - self . yielded ;
493503 ( remaining, Some ( remaining) )
494504 }
You can’t perform that action at this time.
0 commit comments