| 134 | |
| 135 | impl Actor for Shared { |
| 136 | fn start( |
| 137 | mut self: Box<Self>, |
| 138 | ctx: Context, |
| 139 | resources: ResourceCollection, |
| 140 | ) -> rt::task::JoinHandle<Result<()>> { |
| 141 | let (s1, r1) = unbounded::<u64>(); |
| 142 | let mut s2s = vec![]; |
| 143 | let mut r2s = vec![]; |
| 144 | for _ in 0..self.outputs.len() { |
| 145 | let (s2, r2) = unbounded::<u64>(); |
| 146 | s2s.push(s2); |
| 147 | r2s.push(r2); |
| 148 | } |
| 149 | let inputs = self.inputs.clone(); |
| 150 | if !inputs.is_empty() { |
| 151 | // close in order |
| 152 | crate::rt::task::spawn(async move { |
| 153 | while let Ok(id) = r1.recv().await { |
| 154 | for input in inputs.values() { |
| 155 | input.send_any(DummyEnvelope {}.seal()).await.ok(); |
| 156 | } |
| 157 | for s2 in &s2s { |
| 158 | s2.send(id).await.ok(); |
| 159 | } |
| 160 | } |
| 161 | }); |
| 162 | } |
| 163 | |
| 164 | let mut outputs: HashMap<_, Arc<RwLock<HashMap<_, Sender>>>> = HashMap::new(); |
| 165 | for (k, input) in std::mem::take(&mut self.outputs) { |
| 166 | let demux = Arc::new(RwLock::new(HashMap::new())); |
| 167 | outputs.insert(k, demux.clone()); |
| 168 | let r2 = r2s.pop().unwrap(); |
| 169 | crate::rt::task::spawn(async move { |
| 170 | loop { |
| 171 | match input.recv_any().await { |
| 172 | Ok(msg) => { |
| 173 | let outputs = demux.read().await; |
| 174 | let output = outputs |
| 175 | .get( |
| 176 | msg.info() |
| 177 | .transfer_addr |
| 178 | .as_ref() |
| 179 | .expect("lost transfer_address"), |
| 180 | ) |
| 181 | .expect("unexpected transfer_address"); |
| 182 | output.send_any(msg).await.ok(); |
| 183 | } |
| 184 | _ if !input.is_closed() => { |
| 185 | if let Ok(id) = r2.recv().await { |
| 186 | demux.write().await.remove(&id); |
| 187 | } |
| 188 | } |
| 189 | _ => break, |
| 190 | } |
| 191 | } |
| 192 | }); |
| 193 | } |