22
33use  std:: rc:: Rc ; 
44use  std:: cell:: RefCell ; 
5- use  std:: collections:: { VecDeque ,  HashMap } ; 
5+ use  std:: collections:: { VecDeque ,  HashMap ,  hash_map :: Entry } ; 
66use  std:: sync:: mpsc:: { Sender ,  Receiver } ; 
77
88use  bytes:: arc:: Bytes ; 
@@ -28,7 +28,6 @@ pub struct ProcessBuilder {
2828    peers :   usize ,                       // number of peer allocators. 
2929    pushers :  Vec < Receiver < MergeQueue > > ,  // for pushing bytes at other workers. 
3030    pullers :  Vec < Sender < MergeQueue > > ,    // for pulling bytes from other workers. 
31-     // signal:  Signal, 
3231} 
3332
3433impl  ProcessBuilder  { 
@@ -80,11 +79,11 @@ impl ProcessBuilder {
8079            peers :  self . peers , 
8180            events :  Rc :: new ( RefCell :: new ( VecDeque :: new ( ) ) ) , 
8281            canaries :  Rc :: new ( RefCell :: new ( Vec :: new ( ) ) ) , 
82+             channel_id_bound :  None , 
8383            staged :  Vec :: new ( ) , 
8484            sends, 
8585            recvs, 
8686            to_local :  HashMap :: new ( ) , 
87-             // _signal: self.signal, 
8887        } 
8988    } 
9089} 
@@ -108,7 +107,8 @@ pub struct ProcessAllocator {
108107
109108    canaries :  Rc < RefCell < Vec < usize > > > , 
110109
111-     // _signal:     Signal, 
110+     channel_id_bound :  Option < usize > , 
111+ 
112112    // sending, receiving, and responding to binary buffers. 
113113    staged :      Vec < Bytes > , 
114114    sends :       Vec < Rc < RefCell < SendEndpoint < MergeQueue > > > > ,  // sends[x] -> goes to thread x. 
@@ -121,6 +121,12 @@ impl Allocate for ProcessAllocator {
121121    fn  peers ( & self )  -> usize  {  self . peers  } 
122122    fn  allocate < T :  Data > ( & mut  self ,  identifier :  usize )  -> ( Vec < Box < dyn  Push < Message < T > > > > ,  Box < dyn  Pull < Message < T > > > )  { 
123123
124+         // Assume and enforce in-order identifier allocation. 
125+         if  let  Some ( bound)  = self . channel_id_bound  { 
126+             assert ! ( bound < identifier) ; 
127+         } 
128+         self . channel_id_bound  = Some ( identifier) ; 
129+ 
124130        let  mut  pushes = Vec :: < Box < dyn  Push < Message < T > > > > :: new ( ) ; 
125131
126132        for  target_index in  0  .. self . peers ( )  { 
@@ -158,11 +164,15 @@ impl Allocate for ProcessAllocator {
158164        // Check for channels whose `Puller` has been dropped. 
159165        let  mut  canaries = self . canaries . borrow_mut ( ) ; 
160166        for  dropped_channel in  canaries. drain ( ..)  { 
161-             let  dropped  =
167+             let  _dropped  =
162168            self . to_local 
163169                . remove ( & dropped_channel) 
164170                . expect ( "non-existent channel dropped" ) ; 
165-             assert ! ( dropped. borrow( ) . is_empty( ) ) ; 
171+             // Borrowed channels may be non-empty, if the dataflow was forcibly 
172+             // dropped. The contract is that if a dataflow is dropped, all other 
173+             // workers will drop the dataflow too, without blocking indefinitely 
174+             // on events from it. 
175+             // assert!(dropped.borrow().is_empty()); 
166176        } 
167177        std:: mem:: drop ( canaries) ; 
168178
@@ -185,15 +195,23 @@ impl Allocate for ProcessAllocator {
185195                    let  _ = peel. extract_to ( 40 ) ; 
186196
187197                    // Increment message count for channel. 
198+                     // Safe to do this even if the channel has been dropped. 
188199                    events. push_back ( ( header. channel ,  Event :: Pushed ( 1 ) ) ) ; 
189200
190201                    // Ensure that a queue exists. 
191-                     // We may receive data before allocating, and shouldn't block. 
192-                     self . to_local 
193-                         . entry ( header. channel ) 
194-                         . or_insert_with ( || Rc :: new ( RefCell :: new ( VecDeque :: new ( ) ) ) ) 
195-                         . borrow_mut ( ) 
196-                         . push_back ( peel) ; 
202+                     match  self . to_local . entry ( header. channel )  { 
203+                         Entry :: Vacant ( entry)  => { 
204+                             // We may receive data before allocating, and shouldn't block. 
205+                             if  self . channel_id_bound . map ( |b| b < header. channel ) . unwrap_or ( true )  { 
206+                                 entry. insert ( Rc :: new ( RefCell :: new ( VecDeque :: new ( ) ) ) ) 
207+                                     . borrow_mut ( ) 
208+                                     . push_back ( peel) ; 
209+                             } 
210+                         } 
211+                         Entry :: Occupied ( mut  entry)  => { 
212+                             entry. get_mut ( ) . borrow_mut ( ) . push_back ( peel) ; 
213+                         } 
214+                     } 
197215                } 
198216                else  { 
199217                    println ! ( "failed to read full header!" ) ; 
0 commit comments