1
1
use std:: {
2
- collections:: { hash_map, HashMap , VecDeque } ,
2
+ cell:: RefCell ,
3
+ collections:: { binary_heap:: PeekMut , hash_map, BinaryHeap , HashMap , VecDeque } ,
3
4
convert:: TryFrom ,
4
5
mem,
5
6
} ;
@@ -50,7 +51,7 @@ pub struct Streams {
50
51
/// permitted to open but which have not yet been opened.
51
52
send_streams : usize ,
52
53
/// Streams with outgoing data queued
53
- pending : VecDeque < StreamId > ,
54
+ pending : BinaryHeap < PendingLevel > ,
54
55
55
56
events : VecDeque < StreamEvent > ,
56
57
/// Streams blocked on connection-level flow control or stream window space
@@ -105,7 +106,7 @@ impl Streams {
105
106
opened : [ false , false ] ,
106
107
next_reported_remote : [ 0 , 0 ] ,
107
108
send_streams : 0 ,
108
- pending : VecDeque :: new ( ) ,
109
+ pending : BinaryHeap :: new ( ) ,
109
110
events : VecDeque :: new ( ) ,
110
111
connection_blocked : Vec :: new ( ) ,
111
112
max_data : 0 ,
@@ -272,7 +273,7 @@ impl Streams {
272
273
self . unacked_data += len as u64 ;
273
274
trace ! ( stream = %id, "wrote {} bytes" , len) ;
274
275
if !was_pending {
275
- self . pending . push_back ( id ) ;
276
+ push_pending ( & mut self . pending , id , stream . priority ) ;
276
277
}
277
278
Ok ( len)
278
279
}
@@ -393,7 +394,7 @@ impl Streams {
393
394
let was_pending = stream. is_pending ( ) ;
394
395
stream. finish ( ) ?;
395
396
if !was_pending {
396
- self . pending . push_back ( id ) ;
397
+ push_pending ( & mut self . pending , id , stream . priority ) ;
397
398
}
398
399
Ok ( ( ) )
399
400
}
@@ -423,6 +424,25 @@ impl Streams {
423
424
Ok ( ( ) )
424
425
}
425
426
427
+ pub fn set_priority ( & mut self , id : StreamId , priority : i32 ) -> Result < ( ) , UnknownStream > {
428
+ let stream = match self . send . get_mut ( & id) {
429
+ Some ( ss) => ss,
430
+ None => return Err ( UnknownStream { _private : ( ) } ) ,
431
+ } ;
432
+
433
+ stream. priority = priority;
434
+ Ok ( ( ) )
435
+ }
436
+
437
+ pub fn priority ( & mut self , id : StreamId ) -> Result < i32 , UnknownStream > {
438
+ let stream = match self . send . get_mut ( & id) {
439
+ Some ( ss) => ss,
440
+ None => return Err ( UnknownStream { _private : ( ) } ) ,
441
+ } ;
442
+
443
+ Ok ( stream. priority )
444
+ }
445
+
426
446
pub fn reset_acked ( & mut self , id : StreamId ) {
427
447
match self . send . entry ( id) {
428
448
hash_map:: Entry :: Vacant ( _) => { }
@@ -594,14 +614,21 @@ impl Streams {
594
614
Some ( x) => x,
595
615
None => break ,
596
616
} ;
617
+ let mut level = match self . pending . peek_mut ( ) {
618
+ Some ( x) => x,
619
+ None => break ,
620
+ } ;
597
621
// Poppping data from the front of the queue, storing as much data
598
622
// as possible in a single frame, and enqueing sending further
599
623
// remaining data at the end of the queue helps with fairness.
600
624
// Other streams will have a chance to write data before we touch
601
625
// this stream again.
602
- let id = match self . pending . pop_front ( ) {
626
+ let id = match level . queue . get_mut ( ) . pop_front ( ) {
603
627
Some ( x) => x,
604
- None => break ,
628
+ None => {
629
+ PeekMut :: pop ( level) ;
630
+ continue ;
631
+ }
605
632
} ;
606
633
let stream = match self . send . get_mut ( & id) {
607
634
Some ( s) => s,
@@ -622,7 +649,12 @@ impl Streams {
622
649
stream. fin_pending = false ;
623
650
}
624
651
if stream. is_pending ( ) {
625
- self . pending . push_back ( id) ;
652
+ if level. priority == stream. priority {
653
+ level. queue . get_mut ( ) . push_back ( id) ;
654
+ } else {
655
+ drop ( level) ;
656
+ push_pending ( & mut self . pending , id, stream. priority ) ;
657
+ }
626
658
}
627
659
628
660
let meta = frame:: StreamMeta { id, offsets, fin } ;
@@ -691,7 +723,7 @@ impl Streams {
691
723
Some ( x) => x,
692
724
} ;
693
725
if !stream. is_pending ( ) {
694
- self . pending . push_back ( frame. id ) ;
726
+ push_pending ( & mut self . pending , frame. id , stream . priority ) ;
695
727
}
696
728
stream. fin_pending |= frame. fin ;
697
729
stream. pending . retransmit ( frame. offsets ) ;
@@ -708,7 +740,7 @@ impl Streams {
708
740
continue ;
709
741
}
710
742
if !stream. is_pending ( ) {
711
- self . pending . push_back ( id ) ;
743
+ push_pending ( & mut self . pending , id , stream . priority ) ;
712
744
}
713
745
stream. pending . retransmit_all_for_0rtt ( ) ;
714
746
}
@@ -916,6 +948,47 @@ impl Streams {
916
948
}
917
949
}
918
950
951
+ fn push_pending ( pending : & mut BinaryHeap < PendingLevel > , id : StreamId , priority : i32 ) {
952
+ for level in pending. iter ( ) {
953
+ if priority == level. priority {
954
+ level. queue . borrow_mut ( ) . push_back ( id) ;
955
+ return ;
956
+ }
957
+ }
958
+ let mut queue = VecDeque :: new ( ) ;
959
+ queue. push_back ( id) ;
960
+ pending. push ( PendingLevel {
961
+ queue : RefCell :: new ( queue) ,
962
+ priority,
963
+ } ) ;
964
+ }
965
+
966
+ struct PendingLevel {
967
+ // RefCell is needed because BinaryHeap doesn't have an iter_mut()
968
+ queue : RefCell < VecDeque < StreamId > > ,
969
+ priority : i32 ,
970
+ }
971
+
972
+ impl PartialEq for PendingLevel {
973
+ fn eq ( & self , other : & Self ) -> bool {
974
+ self . priority . eq ( & other. priority )
975
+ }
976
+ }
977
+
978
+ impl PartialOrd for PendingLevel {
979
+ fn partial_cmp ( & self , other : & Self ) -> Option < std:: cmp:: Ordering > {
980
+ Some ( self . cmp ( other) )
981
+ }
982
+ }
983
+
984
+ impl Eq for PendingLevel { }
985
+
986
+ impl Ord for PendingLevel {
987
+ fn cmp ( & self , other : & Self ) -> std:: cmp:: Ordering {
988
+ self . priority . cmp ( & other. priority )
989
+ }
990
+ }
991
+
919
992
/// Application events about streams
920
993
#[ derive( Debug ) ]
921
994
pub enum StreamEvent {
@@ -1209,4 +1282,28 @@ mod tests {
1209
1282
TransportErrorCode :: FLOW_CONTROL_ERROR
1210
1283
) ;
1211
1284
}
1285
+
1286
+ #[ test]
1287
+ fn stream_priority ( ) {
1288
+ let mut server = make ( Side :: Server ) ;
1289
+ server. set_params ( & TransportParameters {
1290
+ initial_max_streams_bidi : 3u32 . into ( ) ,
1291
+ initial_max_data : 10u32 . into ( ) ,
1292
+ initial_max_stream_data_bidi_remote : 10u32 . into ( ) ,
1293
+ ..Default :: default ( )
1294
+ } ) ;
1295
+ let id_high = server. open ( Dir :: Bi ) . unwrap ( ) ;
1296
+ let id_mid = server. open ( Dir :: Bi ) . unwrap ( ) ;
1297
+ let id_low = server. open ( Dir :: Bi ) . unwrap ( ) ;
1298
+ server. set_priority ( id_low, -1 ) . unwrap ( ) ;
1299
+ server. set_priority ( id_high, 1 ) . unwrap ( ) ;
1300
+ server. write ( id_mid, b"mid" ) . unwrap ( ) ;
1301
+ server. write ( id_low, b"low" ) . unwrap ( ) ;
1302
+ server. write ( id_high, b"high" ) . unwrap ( ) ;
1303
+ let mut buf = Vec :: with_capacity ( 40 ) ;
1304
+ let meta = server. write_stream_frames ( & mut buf, 40 ) ;
1305
+ assert_eq ! ( meta[ 0 ] . id, id_high) ;
1306
+ assert_eq ! ( meta[ 1 ] . id, id_mid) ;
1307
+ assert_eq ! ( meta[ 2 ] . id, id_low) ;
1308
+ }
1212
1309
}
0 commit comments