@@ -25,11 +25,11 @@ pub use sync::ReadLimiter;
2525#[ cfg( feature = "sync_reader" ) ]
2626mod sync {
2727 use crate :: { Error , Result } ;
28- use core:: sync:: atomic:: { AtomicUsize , Ordering } ;
28+ use core:: sync:: atomic:: { AtomicUsize , AtomicBool , Ordering } ;
2929
3030 pub struct ReadLimiter {
31- pub limit : usize ,
32- pub read : AtomicUsize ,
31+ pub limit : AtomicUsize ,
32+ pub limit_reached : AtomicBool ,
3333 }
3434
3535 impl ReadLimiter {
@@ -39,21 +39,27 @@ mod sync {
3939 }
4040
4141 ReadLimiter {
42- limit : limit as usize ,
43- read : AtomicUsize :: new ( 0 ) ,
42+ limit : AtomicUsize :: new ( limit as usize ) ,
43+ limit_reached : AtomicBool :: new ( false ) ,
4444 }
4545 }
4646
4747 #[ inline]
4848 pub fn can_read ( & self , amount : usize ) -> Result < ( ) > {
49- let read = self . read . load ( Ordering :: Relaxed ) + amount;
49+ let limit_reached = self . limit_reached . load ( Ordering :: Relaxed ) ;
50+ if limit_reached {
51+ return Err ( Error :: failed ( format ! ( "read limit exceeded" ) ) ) ;
52+ }
5053
51- if read > self . limit {
52- Err ( Error :: failed ( format ! ( "read limit exceeded" ) ) )
53- } else {
54- self . read . fetch_add ( amount, Ordering :: Relaxed ) ;
55- Ok ( ( ) )
54+ 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 ) ;
59+ return Err ( Error :: failed ( format ! ( "read limit exceeded" ) ) ) ;
5660 }
61+
62+ Ok ( ( ) )
5763 }
5864 }
5965}
@@ -63,8 +69,8 @@ pub use unsync::ReadLimiter;
6369
6470#[ cfg( not( feature = "sync_reader" ) ) ]
6571mod unsync {
66- use core:: cell:: Cell ;
6772 use crate :: { Error , Result } ;
73+ use core:: cell:: Cell ;
6874
6975 pub struct ReadLimiter {
7076 pub limit : Cell < u64 > ,
0 commit comments