use std::collections::VecDeque;
use std::io::Write;
use std::sync::{Arc, Mutex};
use crossbeam_channel as channel;
use serialport::SerialPort;
pub(crate) struct WritePayload {
pub data: Vec<u8>,
pub response_tx: Option<channel::Sender<Vec<u8>>>,
}
pub(crate) fn writer_thread(
mut port: Box<dyn SerialPort>,
rx: channel::Receiver<WritePayload>,
pending_responses: Arc<Mutex<VecDeque<channel::Sender<Vec<u8>>>>>,
) {
let mut coalesced = Vec::with_capacity(512);
let mut response_txs: Vec<channel::Sender<Vec<u8>>> = Vec::new();
loop {
let payload = match rx.recv() {
Ok(p) => p,
Err(_) => return,
};
coalesced.clear();
response_txs.clear();
coalesced.extend_from_slice(&payload.data);
if let Some(tx) = payload.response_tx {
response_txs.push(tx);
}
while let Ok(payload) = rx.try_recv() {
coalesced.extend_from_slice(&payload.data);
if let Some(tx) = payload.response_tx {
response_txs.push(tx);
}
}
if !response_txs.is_empty() {
let mut pending = pending_responses.lock().unwrap();
for tx in response_txs.drain(..) {
pending.push_back(tx);
}
}
if port.write_all(&coalesced).is_err() {
return;
}
let _ = port.flush();
}
}