itertools
itertools copied to clipboard
Chunks is not Sync
I'd like to use a shared iterator to dispense work items to threads, but it seems I can't.
Is this intentional?
Is there a better way to do this with itertools?
let chunks = std::sync::Arc::new(std::sync::Mutex::new(itertools::Itertools::chunks(0..100, 10).into_iter()));
{
let chunks = chunks.clone();
std::thread::spawn(move || {
while let Ok(Some(v)) = chunks.lock().map(|mut x| (*x).next()) {
for e in v {
println!("{:?}", e);
}
}
});
}
So first of I was wondering why the Arc<Mutex> didn't automatically make it Sync. Turns out that references to Cell or RefCell are not Ok. The Compiler can't guarantee that there is no other reference to the same Cell that would allow data to be modified unchecked. The top answer on the following stackoverflow question probably does a better job of explaining it. https://stackoverflow.com/questions/52801244/compiler-says-that-data-cannot-be-shared-between-threads-safely-even-though-the
As for why it isn't made sync, Arcs and Mutexes usually have a runtime-cost for being threadsafe. Also sharing an iterator like that across threads seems to be a bad idea inherently.
How to work around this depends on what you are trying to do. Your workload requires a lot of mutating of the objects use a Channel if you just need reading access crossbeams scoped threads might be for you.
small crossbeam example:
let worker_count = 3;
let data = "Hello, I am an input string with data....";
crossbeam::scope(|s| {
for i in 0..worker_count {
s.spawn(move |_| {
println!("{}", &data[i..].chars().chunks(3).into_iter().step_by(worker_count).flatten().collect::<String>());
});
}
}).unwrap();
With that said I think this can be closed?
I would add using rayon to the suggestions since it's made pretty much for this usecase