Skip to content

Commit fdf06db

Browse files
authored
Merge pull request #89 from nwtnni/master
2 parents 9d05aee + 33f151b commit fdf06db

1 file changed

Lines changed: 11 additions & 1 deletion

File tree

src/lib.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff 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
}

0 commit comments

Comments
 (0)