Как использовать последовательный порт в нескольких потоках в Rust? - PullRequest
0 голосов
/ 23 ноября 2018

Я пытаюсь читать и записывать в свой последовательный порт в Linux для связи с микроконтроллером, и я пытаюсь сделать это в Rust.

Мой обычный шаблон при разработке, скажем, на C ++ или Python - этоу меня два потока: один, который периодически отправляет запросы по последовательному каналу, и другой, который читает байты из буфера и обрабатывает их.

В Rust у меня возникают проблемы с проверкой заимствований при использовании последовательного ящика.Это имеет смысл для меня, почему это так, но я не уверен, как будет выглядеть проектирование интерфейса асинхронной связи в Rust.Вот фрагмент моего источника:

let mut port = serial::open(&device_path.as_os_str()).unwrap();
let request_temperature: Vec<u8> = vec![0xAA];

thread::spawn(|| {
    let mut buffer: Vec<u8> = Vec::new();
    loop {
        let _bytes_read = port.read(&mut buffer);
        // process data
        thread::sleep(Duration::from_millis(100));
    }
});

loop {
    port.write(&request_temperature);
    thread::sleep(Duration::from_millis(1000));
}

Как я могу эмулировать эту функцию, когда у меня есть два потока, удерживающие изменяемый ресурс в Rust?Я знаю, что поскольку этот конкретный пример может быть выполнен в одном потоке, но я думаю, что для более крупной программы это может быть несколько потоков.

1 Ответ

0 голосов
/ 23 ноября 2018

Вы можете обернуть свой порт в Arc и Mutex, тогда вы можете написать что-то вроде:

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

struct Port;
impl Port {
    pub fn read(&mut self, _v: &mut Vec<u8>) {
        println!("READING...");
    }
    pub fn write(&mut self, _v: &Vec<u8>) {
        println!("WRITING...");
    }
}

pub fn main() {
    let mut port = Arc::new(Mutex::new(Port));
    let p2 = port.clone();

    let handle = thread::spawn(move || {
        let mut buffer: Vec<u8> = Vec::new();
        for j in 0..100 {
            let _bytes_read = p2.lock().unwrap().read(&mut buffer);
            thread::sleep(Duration::from_millis(10));
        }
    });

    let request_temperature: Vec<u8> = vec![0xAA];
    for i in 0..10 {
        port.lock().unwrap().write(&request_temperature);
        thread::sleep(Duration::from_millis(100));
    }

    handle.join();
}

Так что этобудет работать на тестовой машине, я заменил последовательный порт классом заглушки, уменьшил количество снов и заменил бесконечный цикл некоторыми конечными циклами.

Хотя это работает, вы, вероятно, действительно захотите правильной связимежду потоками на каком-то этапе, и в этот момент вы захотите посмотреть std::sync::mpsc::channel

...