rust - Is there any way to implement the Send trait for ZipFile? -


i want read .zip file in different thread using zip crate.

extern crate zip;  use zip::ziparchive; use zip::read::zipfile; use std::fs::file; use std::io::bufreader; use std::thread;  fn compute_hashes(mut file: zipfile) {     let reader_thread= thread::spawn(move || {         let mut reader = bufreader::new(file);         /* ... */     }); }  fn main() {     let mut file = file::open(r"facebook-jakubonderka.zip").unwrap();     let mut zip = ziparchive::new(file).unwrap();      in 0..zip.len() {         let mut inside = zip.by_index(i).unwrap();          if !inside.name().ends_with("/") { // skip directories             println!("filename: {}", inside.name());             compute_hashes(inside);         }     } } 

but compiler shows me error:

error[e0277]: trait bound `std::io::read: std::marker::send` not satisfied   --> src/main.rs:10:24    | 10 |     let reader_thread= thread::spawn(move || {    |                        ^^^^^^^^^^^^^ `std::io::read` cannot sent between threads safely    |    = help: trait `std::marker::send` not implemented `std::io::read`    = note: required because of requirements on impl of `std::marker::send` `&mut std::io::read`    = note: required because appears within type `std::io::take<&mut std::io::read>`    = note: required because appears within type `zip::crc32::crc32reader<std::io::take<&mut std::io::read>>`    = note: required because appears within type `zip::read::zipfilereader<'_>`    = note: required because appears within type `zip::read::zipfile<'_>`    = note: required because appears within type `[closure@src/main.rs:10:38: 13:6 file:zip::read::zipfile<'_>]`    = note: required `std::thread::spawn` 

but same works type std::fs::file. necessary fix zip crate or there other method?

this a limitation of zip crate's api , can't change anything. problem file ziparchive created calling new , passing reader -- implements read , seek. these requirements reader (in particular, reader doesn't need clone). thus, whole ziparchive can own 1 reader.

but ziparchive able produce zipfiles implement read themselves. how work if whole ziparchive has 1 reader? through sharing! reader shared between archive , files. sharing not thread save! mutable reference reader stored in each zipfile -- violates rust's core principle.

this known issue of crate , being discussed on github issue tracker.


so can now? not whole lot, few possibilities (as mentioned library author) might ok use case:

  • you decompress whole file memory first, send raw data thread calculations on it. like:

    let data = vec::new(); bufreader::new(file).read_to_end(&mut data)?; let reader_thread= thread::spawn(move || {     // stuff `data` }); 

    but if want compute cheap hash function on files, loading contents memory slower computing hash on fly , might infeasible if files big.

  • creating 1 ziparchive each thread. might slow if have many small files in archive...


a tiny hint: starting thread costs time. don't want start thread each unit of work, rather maintain fixed number of threads in thread pool, manage work in queue , assign work idle worker threads. the threadpool crate might serve needs.


Comments

Popular posts from this blog

PHP and MySQL WP -

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

go - golang pprof for c library code -