(
atoms: &[A],
partitions: &[MoleculePartition],
progress_every: usize,
num_threads: usize,
callback: F,
)
| 274 | } |
| 275 | |
| 276 | fn run_threaded<A, R, F, E>( |
| 277 | atoms: &[A], |
| 278 | partitions: &[MoleculePartition], |
| 279 | progress_every: usize, |
| 280 | num_threads: usize, |
| 281 | callback: F, |
| 282 | ) -> Result<(Vec<R>, Vec<ProgressSnapshot>), HpcParallelError> |
| 283 | where |
| 284 | A: Sync, |
| 285 | R: Send, |
| 286 | F: Fn(&[A]) -> Result<R, E> + Send + Sync, |
| 287 | E: Display, |
| 288 | { |
| 289 | let started = Instant::now(); |
| 290 | let total = partitions.len(); |
| 291 | let callback = Arc::new(callback); |
| 292 | |
| 293 | let (job_tx, job_rx) = mpsc::channel::<MoleculePartition>(); |
| 294 | let job_rx = Arc::new(Mutex::new(job_rx)); |
| 295 | let (result_tx, result_rx) = |
| 296 | mpsc::channel::<(MoleculePartition, Result<R, HpcParallelError>)>(); |
| 297 | |
| 298 | thread::scope(|scope| { |
| 299 | let mut workers = Vec::with_capacity(num_threads); |
| 300 | for _ in 0..num_threads { |
| 301 | let rx = Arc::clone(&job_rx); |
| 302 | let tx = result_tx.clone(); |
| 303 | let cb = Arc::clone(&callback); |
| 304 | workers.push(scope.spawn(move || loop { |
| 305 | let next = { |
| 306 | let guard = rx.lock().expect("job receiver mutex should not be poisoned"); |
| 307 | guard.recv() |
| 308 | }; |
| 309 | let part = match next { |
| 310 | Ok(part) => part, |
| 311 | Err(_) => break, |
| 312 | }; |
| 313 | let res = cb(&atoms[part.start..part.end]).map_err(|err| { |
| 314 | HpcParallelError::CallbackFailed { |
| 315 | molecule_id: part.molecule_id, |
| 316 | message: err.to_string(), |
| 317 | } |
| 318 | }); |
| 319 | if tx.send((part, res)).is_err() { |
| 320 | break; |
| 321 | } |
| 322 | })); |
| 323 | } |
| 324 | drop(result_tx); |
| 325 | |
| 326 | for part in partitions { |
| 327 | if job_tx.send(*part).is_err() { |
| 328 | return Err(HpcParallelError::ChannelClosed("queueing jobs")); |
| 329 | } |
| 330 | } |
| 331 | drop(job_tx); |
| 332 | |
| 333 | let mut ordered: Vec<Option<R>> = (0..total).map(|_| None).collect(); |
no test coverage detected