Skip to content

Commit 83c76be

Browse files
appaquetdwrensha
authored andcommitted
Atomic read limiter: better logic
1 parent ceb5649 commit 83c76be

File tree

1 file changed

+7
-9
lines changed

1 file changed

+7
-9
lines changed

capnp/src/private/read_limiter.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,10 @@ pub use sync::ReadLimiter;
2525
#[cfg(feature = "sync_reader")]
2626
mod sync {
2727
use crate::{Error, Result};
28-
use core::sync::atomic::{AtomicUsize, AtomicBool, Ordering};
28+
use core::sync::atomic::{AtomicUsize, Ordering};
2929

3030
pub struct ReadLimiter {
3131
pub limit: AtomicUsize,
32-
pub limit_reached: AtomicBool,
3332
}
3433

3534
impl ReadLimiter {
@@ -40,22 +39,21 @@ mod sync {
4039

4140
ReadLimiter {
4241
limit: AtomicUsize::new(limit as usize),
43-
limit_reached: AtomicBool::new(false),
4442
}
4543
}
4644

4745
#[inline]
4846
pub fn can_read(&self, amount: usize) -> Result<()> {
49-
let limit_reached = self.limit_reached.load(Ordering::Relaxed);
50-
if limit_reached {
47+
let cur_limit = self.limit.load(Ordering::Relaxed);
48+
if cur_limit < amount {
5149
return Err(Error::failed(format!("read limit exceeded")));
5250
}
5351

5452
let prev_limit = self.limit.fetch_sub(amount, Ordering::Relaxed);
55-
if prev_limit == amount {
56-
self.limit_reached.store(true, Ordering::Relaxed);
57-
} else if prev_limit < amount {
58-
self.limit_reached.store(true, Ordering::Relaxed);
53+
if prev_limit < amount {
54+
// if the previous limit was lower than the amount we read, the limit has underflowed
55+
// and wrapped around so we need to reset it to 0 for next reader to fail
56+
self.limit.store(0, Ordering::Relaxed);
5957
return Err(Error::failed(format!("read limit exceeded")));
6058
}
6159

0 commit comments

Comments
 (0)