@@ -5,11 +5,22 @@ use futures::{
5
5
Sink ,
6
6
Stream ,
7
7
} ;
8
+ use log:: * ;
8
9
use std:: { pin:: Pin , sync:: Arc , task:: Poll } ;
9
10
10
- pub fn bounded < T > ( size : usize ) -> ( Publisher < T > , Subscriber < T > ) {
11
- let ( sender, receiver) = raw_bounded ( size) ;
11
+ const LOG_TARGET : & str = "tari_broadcast_channel::async_channel" ;
12
+ const ID_MULTIPLIER : usize = 10_000 ;
13
+
14
+ pub fn bounded < T > ( size : usize , receiver_id : usize ) -> ( Publisher < T > , Subscriber < T > ) {
15
+ let ( sender, receiver) = raw_bounded ( size, receiver_id) ;
12
16
let ( waker, sleeper) = alarm ( ) ;
17
+ debug ! (
18
+ target: LOG_TARGET ,
19
+ "Buffer created with ID '{}' ({}) and size {}, consecutive subscriptions add 1 to the ID." ,
20
+ receiver_id * ID_MULTIPLIER ,
21
+ receiver_id,
22
+ size
23
+ ) ;
13
24
( Publisher { sender, waker } , Subscriber { receiver, sleeper } )
14
25
}
15
26
@@ -62,17 +73,40 @@ impl<T> Stream for Subscriber<T> {
62
73
fn poll_next ( self : Pin < & mut Self > , cx : & mut task:: Context < ' _ > ) -> Poll < Option < Self :: Item > > {
63
74
self . sleeper . register ( cx. waker ( ) ) ;
64
75
match self . receiver . try_recv ( ) {
65
- Ok ( item) => Poll :: Ready ( Some ( item) ) ,
66
- Err ( error) => match error {
67
- TryRecvError :: Empty => Poll :: Pending ,
68
- TryRecvError :: Disconnected => Poll :: Ready ( None ) ,
76
+ Ok ( item) => {
77
+ if self . receiver . get_dropped_messages_state ( ) {
78
+ debug ! (
79
+ target: LOG_TARGET ,
80
+ "Subscriber with ID '{}' has {} buffer messages dropped." ,
81
+ self . receiver. get_id( ) ,
82
+ self . receiver. get_dropped_messages_count( )
83
+ ) ;
84
+ }
85
+ Poll :: Ready ( Some ( item) )
86
+ } ,
87
+ Err ( error) => {
88
+ trace ! (
89
+ target: LOG_TARGET ,
90
+ "Subscriber with ID '{}', receive error: '{}'" ,
91
+ self . receiver. get_id( ) ,
92
+ error
93
+ ) ;
94
+ match error {
95
+ TryRecvError :: Empty => Poll :: Pending ,
96
+ TryRecvError :: Disconnected => Poll :: Ready ( None ) ,
97
+ }
69
98
} ,
70
99
}
71
100
}
72
101
}
73
102
74
103
impl < T > Clone for Subscriber < T > {
75
104
fn clone ( & self ) -> Self {
105
+ trace ! (
106
+ target: LOG_TARGET ,
107
+ "Subscriber with ID '{}' was cloned, new subscription." ,
108
+ self . receiver. get_id( )
109
+ ) ;
76
110
Self {
77
111
receiver : self . receiver . clone ( ) ,
78
112
sleeper : self . sleeper . clone ( ) ,
@@ -88,6 +122,22 @@ impl<T: Send> PartialEq for Subscriber<T> {
88
122
89
123
impl < T : Send > Eq for Subscriber < T > { }
90
124
125
+ impl < T > Subscriber < T > {
126
+ /// Returns the receiver id
127
+ pub fn get_receiver_id ( & self ) -> usize {
128
+ self . receiver . get_id ( )
129
+ }
130
+
131
+ /// Returns the amount of dropped messages for the receiver
132
+ pub fn get_dropped_messages_count ( & self ) -> usize {
133
+ self . receiver . get_dropped_messages_count ( )
134
+ }
135
+
136
+ /// Returns the receiver's dropped messgages state for the last message read
137
+ pub fn get_dropped_messages_state ( & self ) -> bool {
138
+ self . receiver . get_dropped_messages_state ( )
139
+ }
140
+ }
91
141
// Helper struct used by sync and async implementations to wake Tasks / Threads
92
142
#[ derive( Debug ) ]
93
143
pub struct Waker {
@@ -154,15 +204,30 @@ pub fn alarm() -> (Waker, Sleeper) {
154
204
155
205
#[ cfg( test) ]
156
206
mod test {
207
+ use crate :: async_channel;
157
208
use futures:: { executor:: block_on, stream, StreamExt } ;
158
209
159
210
#[ test]
160
211
fn channel ( ) {
161
- let ( publisher , subscriber1) = super :: bounded ( 10 ) ;
212
+ let ( publisher1 , subscriber1) = super :: bounded ( 10 , 1 ) ;
162
213
let subscriber2 = subscriber1. clone ( ) ;
214
+ let subscriber3 = subscriber1. clone ( ) ;
215
+
216
+ assert_eq ! ( subscriber1. get_receiver_id( ) , 10000 ) ;
217
+ assert_eq ! ( subscriber2. get_receiver_id( ) , 10001 ) ;
218
+ assert_eq ! ( subscriber3. get_receiver_id( ) , 10002 ) ;
219
+
220
+ let ( publisher2, subscriber4) : ( async_channel:: Publisher < usize > , async_channel:: Subscriber < usize > ) =
221
+ super :: bounded ( 10 , 2 ) ;
222
+ let subscriber5 = subscriber4. clone ( ) ;
223
+ let subscriber6 = subscriber4. clone ( ) ;
224
+
225
+ assert_eq ! ( subscriber4. get_receiver_id( ) , 20000 ) ;
226
+ assert_eq ! ( subscriber5. get_receiver_id( ) , 20001 ) ;
227
+ assert_eq ! ( subscriber6. get_receiver_id( ) , 20002 ) ;
163
228
164
229
block_on ( async move {
165
- stream:: iter ( 1 ..15 ) . map ( |i| Ok ( i) ) . forward ( publisher ) . await . unwrap ( ) ;
230
+ stream:: iter ( 1 ..15 ) . map ( |i| Ok ( i) ) . forward ( publisher1 ) . await . unwrap ( ) ;
166
231
} ) ;
167
232
168
233
let received1: Vec < u32 > = block_on ( async { subscriber1. map ( |x| * x) . collect ( ) . await } ) ;
@@ -171,5 +236,12 @@ mod test {
171
236
let expected = ( 5 ..15 ) . collect :: < Vec < u32 > > ( ) ;
172
237
assert_eq ! ( received1, expected) ;
173
238
assert_eq ! ( received2, expected) ;
239
+ // Test messages discarded
240
+ subscriber3. receiver . try_recv ( ) . unwrap ( ) ;
241
+ assert_eq ! ( subscriber3. receiver. get_dropped_messages_state( ) , true ) ;
242
+ assert_eq ! ( subscriber3. receiver. get_dropped_messages_count( ) , 4 ) ;
243
+ subscriber3. receiver . try_recv ( ) . unwrap ( ) ;
244
+ assert_eq ! ( subscriber3. receiver. get_dropped_messages_state( ) , false ) ;
245
+ assert_eq ! ( subscriber3. receiver. get_dropped_messages_count( ) , 4 ) ;
174
246
}
175
247
}
0 commit comments