1
1
use super :: * ;
2
2
3
3
pub ( crate ) struct Bounded < T > {
4
+ disconnected : bool ,
4
5
cap : usize ,
5
6
sends : VecDeque < ( Waker , Booth < T > ) > ,
6
7
queue : VecDeque < T > ,
@@ -9,51 +10,61 @@ pub(crate) struct Bounded<T> {
9
10
10
11
impl < T > Bounded < T > {
11
12
pub fn new ( cap : usize ) -> Flavor < T > {
12
- Flavor :: Bounded ( Lock :: new ( Self {
13
+ Flavor :: Bounded ( Self {
14
+ disconnected : false ,
13
15
cap,
14
16
sends : VecDeque :: new ( ) ,
15
17
queue : VecDeque :: new ( ) ,
16
18
recvs : VecDeque :: new ( ) ,
17
- } ) )
19
+ } )
18
20
}
19
21
20
22
pub fn disconnect ( & mut self ) {
23
+ self . disconnected = true ;
21
24
self . sends . drain ( ..) . for_each ( |( w, _) | w. wake ( ) ) ;
22
25
self . recvs . drain ( ..) . for_each ( |( w, _) | w. wake ( ) ) ;
23
26
}
24
27
25
- pub fn try_send ( & mut self , item : T ) -> Result < Option < Waker > , T > {
26
- match self . recvs . pop_front ( ) {
27
- Some ( ( waker, booth) ) => {
28
- booth. give ( item) ;
29
- Ok ( Some ( waker) )
30
- } ,
31
- None => if self . queue . len ( ) < self . cap {
32
- self . queue . push_back ( item) ;
33
- Ok ( None )
34
- } else {
35
- Err ( item)
36
- } ,
28
+ pub fn try_send ( & mut self , mut item : T ) -> Result < Option < Waker > , ( T , bool ) > {
29
+ if self . disconnected {
30
+ return Err ( ( item, true ) ) ;
31
+ }
32
+
33
+ loop {
34
+ item = match self . recvs . pop_front ( ) {
35
+ Some ( ( waker, booth) ) => match booth. give ( item) {
36
+ Some ( item) => item,
37
+ None => break Ok ( Some ( waker) ) , // Woke receiver
38
+ } ,
39
+ None => break if self . queue . len ( ) < self . cap {
40
+ self . queue . push_back ( item) ;
41
+ Ok ( None ) // Pushed to queue
42
+ } else {
43
+ Err ( ( item, false ) ) // Queue is full
44
+ } ,
45
+ } ;
37
46
}
38
47
}
39
48
40
- pub fn try_recv ( & mut self ) -> Option < ( Option < Waker > , T ) > {
49
+ pub fn try_recv ( & mut self ) -> Result < ( Option < Waker > , T ) , bool > {
41
50
self . queue
42
51
. pop_front ( )
43
52
. map ( |item| {
44
53
// We just made some space in the queue so we need to pull the next waiting sender too
45
- loop {
54
+ let w = loop {
46
55
if let Some ( ( waker, item) ) = self . sends . pop_front ( ) {
47
56
// Attempt to take the item in the slot. If the item does not exist, it must be because the sender
48
57
// cancelled sending (perhaps due to a timeout). In such a case, don't bother to wake the sender (because
49
58
// it should already have been woken by the timeout alarm) and skip to the next entry.
50
59
if let Some ( item) = item. try_take ( ) {
51
- break ( Some ( waker) , item) ;
60
+ self . queue . push_back ( item) ;
61
+ break Some ( waker) ;
52
62
}
53
63
} else {
54
- break ( None , item ) ;
64
+ break None ;
55
65
}
56
- }
66
+ } ;
67
+ ( w, item)
57
68
} )
58
69
. or_else ( || {
59
70
while let Some ( ( waker, item) ) = self . sends . pop_front ( ) {
@@ -66,23 +77,28 @@ impl<T> Bounded<T> {
66
77
}
67
78
None
68
79
} )
80
+ . ok_or ( self . disconnected )
69
81
}
70
82
71
- pub fn send ( & mut self , item : T , waker : impl FnOnce ( ) -> Waker ) -> Result < Option < Waker > , Booth < T > > {
83
+ pub fn send ( & mut self , item : T , waker : impl FnOnce ( ) -> Waker ) -> Result < Option < Waker > , Result < Booth < T > , T > > {
72
84
self . try_send ( item)
73
- . map_err ( |item| {
85
+ . map_err ( |( item, d) | if d {
86
+ Err ( item)
87
+ } else {
74
88
let item = Booth :: full ( item) ;
75
89
self . sends . push_back ( ( waker ( ) , item. clone ( ) ) ) ;
76
- item
90
+ Ok ( item)
77
91
} )
78
92
}
79
93
80
- pub fn recv ( & mut self , waker : impl FnOnce ( ) -> Waker ) -> Result < ( Option < Waker > , T ) , Booth < T > > {
94
+ pub fn recv ( & mut self , waker : impl FnOnce ( ) -> Waker ) -> Result < ( Option < Waker > , T ) , Option < Booth < T > > > {
81
95
self . try_recv ( )
82
- . ok_or_else ( || {
96
+ . map_err ( |d| if d {
97
+ None
98
+ } else {
83
99
let item = Booth :: empty ( ) ;
84
100
self . recvs . push_back ( ( waker ( ) , item. clone ( ) ) ) ;
85
- item
101
+ Some ( item)
86
102
} )
87
103
}
88
104
0 commit comments