admin管理员组文章数量:1387392
In the below code I'm copying a file(worker thread) and want to print the progress of the file copy operation in main thread. I would like to know, if it's possible to get the file/seek position of the reader file opened in worker thread asynchronously, so that progress info can be notified to main thread. This is what I've written so far
use std::io::{Read, Write};
use std::fs;
use std::sync::{Arc, Condvar, Mutex};
fn write_to_file<R: Read, W: Write>(mut reader: R, mut writer: W) {
let mut buf = vec![0; 1024];
let mut bytes_read = buf.capacity();
while bytes_read > 0 {
bytes_read = reader.read(&mut buf).expect("failed to read from the file");
if bytes_read > 0 {
writer.write_all(&buf[..bytes_read]).expect("failed to write to the file");
}
}
writer.flush().expect("failed to flush the writer");
}
fn foo(s: Arc<(Condvar, Mutex<i32>)>) {
let &(ref cv, ref m) = &*s;
let src_file = fs::File::open("~/a.txt").expect("unable to open the file");
let dst_file = fs::File::create("~/b.txt").expect("unable to create the file");
write_to_file(src_file, dst_file);
let mut progress = 0;
// get the progress of above file operation using file/seek position of src file
// if possible using async and store it in above progress
// I cannot change the syntax of write_to_file
{
let mut mg = m.lock().unwrap();
*mg = progress;
}
cv.notify_one();
}
fn main() {
let s = Arc::new((Condvar::new(), Mutex::new(0)));
let sa = Arc::clone(&s);
let jh = std::thread::spawn(move || {
foo(sa);
});
let mut prev_progress = 0;
let &(ref cv, ref m) = &*s;
loop {
let mut mg = m.lock().unwrap();
while *mg == prev_progress {
mg = cv.wait(mg).unwrap();
}
prev_progress = *mg;
println!("{}", *mg);
if *mg == 100 {
break;
}
}
jh.join();
}
In the below code I'm copying a file(worker thread) and want to print the progress of the file copy operation in main thread. I would like to know, if it's possible to get the file/seek position of the reader file opened in worker thread asynchronously, so that progress info can be notified to main thread. This is what I've written so far
use std::io::{Read, Write};
use std::fs;
use std::sync::{Arc, Condvar, Mutex};
fn write_to_file<R: Read, W: Write>(mut reader: R, mut writer: W) {
let mut buf = vec![0; 1024];
let mut bytes_read = buf.capacity();
while bytes_read > 0 {
bytes_read = reader.read(&mut buf).expect("failed to read from the file");
if bytes_read > 0 {
writer.write_all(&buf[..bytes_read]).expect("failed to write to the file");
}
}
writer.flush().expect("failed to flush the writer");
}
fn foo(s: Arc<(Condvar, Mutex<i32>)>) {
let &(ref cv, ref m) = &*s;
let src_file = fs::File::open("~/a.txt").expect("unable to open the file");
let dst_file = fs::File::create("~/b.txt").expect("unable to create the file");
write_to_file(src_file, dst_file);
let mut progress = 0;
// get the progress of above file operation using file/seek position of src file
// if possible using async and store it in above progress
// I cannot change the syntax of write_to_file
{
let mut mg = m.lock().unwrap();
*mg = progress;
}
cv.notify_one();
}
fn main() {
let s = Arc::new((Condvar::new(), Mutex::new(0)));
let sa = Arc::clone(&s);
let jh = std::thread::spawn(move || {
foo(sa);
});
let mut prev_progress = 0;
let &(ref cv, ref m) = &*s;
loop {
let mut mg = m.lock().unwrap();
while *mg == prev_progress {
mg = cv.wait(mg).unwrap();
}
prev_progress = *mg;
println!("{}", *mg);
if *mg == 100 {
break;
}
}
jh.join();
}
Share
Improve this question
asked Mar 18 at 7:21
HarryHarry
3,2481 gold badge24 silver badges46 bronze badges
4
|
1 Answer
Reset to default 1Since &File
implements both Read
and Seek
you can simply pass references instead of the values themselves. That gives your foo
function access the &File
and it's Seek
implementation after you pass one copy to write_to_file
:
fn foo(s: Arc<(Condvar, Mutex<u64>)>) {
let &(ref cv, ref m) = &*s;
let mut src_file = &fs::File::open("src/main.rs").expect("unable to open the file");
let dst_file = &fs::File::create("b.txt").expect("unable to create the file");
std::thread::scope(|s| {
let w = s.spawn(move || {
write_to_file(src_file, dst_file);
});
while !w.is_finished() {
std::thread::sleep_ms(1);
let progress = src_file.stream_position().unwrap();
let total = src_file.metadata().unwrap().len();
{
let mut mg = m.lock().unwrap();
*mg = 100 * progress / total;
}
cv.notify_one();
}
*m.lock().unwrap() = 100;
});
}
If you can't easily pass around shared references to the File
, for example because you want to open the File
in a function, you can also use Arc<File>
and clone that instead since it also implements Read
in this way you can share the ownership and avoid having to use a non-static reference.
Since the asynchronous versions of File
do not implement AsyncRead
/AsyncSeek
for references you can't use them in a similar manner.
版权声明:本文标题:multithreading - How to get the fileseek position of a file opened in a thread asynchronously - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744518043a2610281.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
write_to_file
, then it's impossible. – Jmb Commented Mar 18 at 7:31reader thread
opens a file,another thread
can check how much percent it has read based on the current file offset or seek position updated by thereader thread
? – Harry Commented Mar 18 at 7:36Read
ers in general, but not forFile
since it implementsRead
andSeek
for a shared reference&File
in addition to the implementation onFile
. – cafce25 Commented Mar 18 at 8:20Read
required a&mut
reference, which would have prevented reading the position, but you're right, a shared reference is sufficient. – Jmb Commented Mar 18 at 11:25