11use std:: {
22 collections:: VecDeque ,
33 sync:: {
4- atomic:: { AtomicBool , AtomicUsize } ,
4+ atomic:: { AtomicBool , AtomicU64 , AtomicUsize , Ordering } ,
55 Mutex ,
66 } ,
77} ;
88
9+ use crate :: Error ;
10+
911pub struct Chute < T > {
1012 queue : Mutex < VecDeque < T > > ,
1113 clean : AtomicBool ,
@@ -60,6 +62,8 @@ pub struct Shared<T> {
6062 pub ( crate ) waker : futures:: task:: AtomicWaker ,
6163 pub ( crate ) senders : AtomicUsize ,
6264 pub ( crate ) chute_clock : AtomicUsize ,
65+ pub ( crate ) channel_size : AtomicU64 ,
66+ pub ( crate ) capacity : u64 ,
6367 dead : AtomicBool ,
6468}
6569
@@ -70,57 +74,77 @@ impl<T> std::fmt::Debug for Shared<T> {
7074 . field ( "waker" , & self . waker )
7175 . field ( "senders" , & self . senders )
7276 . field ( "chute_clock" , & self . chute_clock )
77+ . field ( "channel_size" , & self . channel_size )
78+ . field ( "capacity" , & self . capacity )
7379 . field ( "dead" , & self . dead )
7480 . finish ( )
7581 }
7682}
7783
7884impl < T > Shared < T > {
79- pub fn new ( concurrency : usize ) -> Self {
85+ pub fn new ( concurrency : usize , capacity : u64 ) -> Self {
8086 Self {
8187 chutes : ( 0 ..concurrency)
8288 . map ( |_| Default :: default ( ) )
8389 . collect :: < Vec < _ > > ( ) ,
8490 waker : futures:: task:: AtomicWaker :: new ( ) ,
8591 senders : AtomicUsize :: new ( 0 ) ,
8692 chute_clock : AtomicUsize :: new ( 0 ) ,
93+ channel_size : AtomicU64 :: new ( 0 ) ,
94+ capacity,
8795 dead : AtomicBool :: new ( false ) ,
8896 }
8997 }
9098
9199 pub fn add_sender ( & self ) {
92- self . senders
93- . fetch_add ( 1 , std:: sync:: atomic:: Ordering :: Release ) ;
100+ self . senders . fetch_add ( 1 , Ordering :: Release ) ;
94101 }
95102
96103 pub fn drop_sender ( & self ) -> usize {
97- self . senders
98- . fetch_sub ( 1 , std:: sync:: atomic:: Ordering :: AcqRel )
104+ self . senders . fetch_sub ( 1 , Ordering :: AcqRel )
99105 }
100106
101107 pub fn choose_chute ( & self ) -> usize {
102- self . chute_clock
103- . fetch_add ( 1 , std:: sync:: atomic:: Ordering :: Relaxed )
104- % self . chutes . len ( )
108+ self . chute_clock . fetch_add ( 1 , Ordering :: Relaxed ) % self . chutes . len ( )
105109 }
106110
107111 pub fn wake ( & self ) {
108112 self . waker . wake ( ) ;
109113 }
110114
111- pub fn send ( & self , chute : usize , value : T ) -> Result < ( ) , T > {
112- if self . dead . load ( std:: sync:: atomic:: Ordering :: Relaxed ) {
113- return Err ( value) ;
115+ pub fn send ( & self , chute : usize , value : T ) -> Result < ( ) , Error < T > > {
116+ if self . dead . load ( Ordering :: Relaxed ) {
117+ return Err ( Error :: Closed ( value) ) ;
118+ }
119+ if self . capacity != u64:: MAX {
120+ let prev = self . channel_size . fetch_add ( 1 , Ordering :: Relaxed ) ;
121+ if self . capacity < prev + 1 {
122+ self . channel_size . fetch_sub ( 1 , Ordering :: Relaxed ) ;
123+ return Err ( Error :: Full ( value) ) ;
124+ }
114125 }
115126 self . send_many_infallible ( chute, [ value] ) ;
116127 Ok ( ( ) )
117128 }
118129
119- pub fn send_many < I : IntoIterator < Item = T > > ( & self , chute : usize , values : I ) -> Result < ( ) , I > {
120- if self . dead . load ( std:: sync:: atomic:: Ordering :: Relaxed ) {
121- return Err ( values) ;
130+ pub fn send_many < I > ( & self , chute : usize , values : I ) -> Result < ( ) , Error < I :: IntoIter > >
131+ where
132+ I : IntoIterator < Item = T > ,
133+ I :: IntoIter : ExactSizeIterator ,
134+ {
135+ let iter = values. into_iter ( ) ;
136+ if self . dead . load ( Ordering :: Relaxed ) {
137+ return Err ( Error :: Closed ( iter) ) ;
138+ }
139+ if self . capacity != u64:: MAX {
140+ let count = iter. len ( ) as u64 ;
141+ let prev = self . channel_size . fetch_add ( count, Ordering :: Relaxed ) ;
142+ if self . capacity < prev + count {
143+ self . channel_size . fetch_sub ( count, Ordering :: Relaxed ) ;
144+ return Err ( Error :: Full ( iter) ) ;
145+ }
122146 }
123- self . send_many_infallible ( chute, values ) ;
147+ self . send_many_infallible ( chute, iter ) ;
124148 Ok ( ( ) )
125149 }
126150
0 commit comments