【问题标题】:How can I force a thread that is blocked reading from a file to resume in Rust?如何强制一个被阻止从文件读取的线程在 Rust 中恢复?
【发布时间】:2016-03-24 23:11:07
【问题描述】:

因为 Rust 没有以非阻塞方式从文件中读取的内置功能,所以我必须生成一个线程来读取文件 /dev/input/fs0 以获取操纵杆事件。假设摇杆未使用(没有可读取的内容),所以读取线程在读取文件时被阻塞。

有没有办法让主线程强制读取线程的阻塞读取恢复,让读取线程干净退出?

在其他语言中,我会简单地在主线程中关闭文件。这将迫使阻塞读取恢复。但是我在 Rust 中没有找到这样做的方法,因为读取需要对文件的可变引用。

【问题讨论】:

  • mio 对这个用途来说太重了吗?
  • @WiSaGaN MIO 明确不处理文件的异步 IO。好好阅读background of async file IO。
  • @Shepmaster OP 看起来不需要异步 IO。非阻塞 IO 可以通过使用 mio 和 RawFd Evented 来实现。
  • @WiSaGaN 知道这是否适用于所有主要平台(Linux、Windows、OS X)?
  • @Shepmaster 不,只是 OP 使用的是/dev/input/fs0,所以至少它不是 Windows。 :p

标签: rust blocking resume


【解决方案1】:

这个想法是只有在有可用数据时才调用File::read。如果没有可用数据,我们检查一个标志来查看主线程是否请求停止。如果没有,请稍候再试。

这是一个使用nonblock crate 的示例:

extern crate nonblock;

use std::fs::File;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;

use nonblock::NonBlockingReader;

fn main() {
    let f = File::open("/dev/stdin").expect("open failed");
    let mut reader = NonBlockingReader::from_fd(f).expect("from_fd failed");

    let exit = Arc::new(Mutex::new(false));
    let texit = exit.clone();

    println!("start reading, type something and enter");

    thread::spawn(move || {
        let mut buf: Vec<u8> = Vec::new();
        while !*texit.lock().unwrap() {
            let s = reader.read_available(&mut buf).expect("io error");
            if s == 0 {
                if reader.is_eof() {
                    println!("eof");
                    break;
                }
            } else {
                println!("read {:?}", buf);
                buf.clear();
            }
            thread::sleep(Duration::from_millis(200));
        }
        println!("stop reading");
    });

    thread::sleep(Duration::from_secs(5));

    println!("closing file");
    *exit.lock().unwrap() = true;

    thread::sleep(Duration::from_secs(2));
    println!("\"stop reading\" was printed before the main exit!");
}

fn read_async<F>(file: File, fun: F) -> thread::JoinHandle<()>
    where F: Send + 'static + Fn(&Vec<u8>)
{
    let mut reader = NonBlockingReader::from_fd(file).expect("from_fd failed");
    let mut buf: Vec<u8> = Vec::new();
    thread::spawn(move || {
        loop {
            let s = reader.read_available(&mut buf).expect("io error");
            if s == 0 {
                if reader.is_eof() {
                    break;
                }
            } else {
                fun(&buf);
                buf.clear();
            }
            thread::sleep(Duration::from_millis(100));
        }
    })
}

这是一个使用 poll 绑定 nix crate 的示例。函数poll 等待(超时)特定事件:

extern crate nix;

use std::io::Read;
use std::os::unix::io::AsRawFd;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;

use nix::poll;

fn main() {
    let mut f = std::fs::File::open("/dev/stdin").expect("open failed");
    let mut pfd = poll::PollFd {
        fd: f.as_raw_fd(),
        events: poll::POLLIN, // is there input data?
        revents: poll::EventFlags::empty(),
    };

    let exit = Arc::new(Mutex::new(false));
    let texit = exit.clone();

    println!("start reading, type something and enter");

    thread::spawn(move || {
        let timeout = 100; // millisecs
        let mut s = unsafe { std::slice::from_raw_parts_mut(&mut pfd, 1) };
        let mut buffer = [0u8; 10];
        loop {
            if poll::poll(&mut s, timeout).expect("poll failed") != 0 {
                let s = f.read(&mut buffer).expect("read failed");
                println!("read {:?}", &buffer[..s]);
            }
            if *texit.lock().unwrap() {
                break;
            }
        }
        println!("stop reading");
    });

    thread::sleep(Duration::from_secs(5));

    println!("closing file");
    *exit.lock().unwrap() = true;

    thread::sleep(Duration::from_secs(2));
    println!("\"stop reading\" was printed before the main exit!");

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多