vor 0.2.1

Cross-platform performance instrumentation with an in-app egui panel and live system and GPU metrics.
Documentation
use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::PathBuf;
use std::sync::mpsc::{Receiver, SyncSender};

use crate::record::format::{self, Header, Record};

/// A unit of work for the writer thread: a user-column declaration, a
/// frame to append, or a flush barrier that replies once everything
/// queued before it is on disk.
pub(crate) enum Msg {
    Decl { id: u16, name: String, unit: String },
    Frame(Record),
    Flush(SyncSender<()>),
}

/// Background writer loop: write the header once, then one lz4 record
/// per message, flushing after each so a tailing reader sees every
/// frame without waiting. Exits when the recorder (and thus the
/// sender) is dropped, which for the process-global recorder is never.
pub(crate) fn run(target: PathBuf, header: Header, rx: Receiver<Msg>) {
    let file = File::create(&target).unwrap_or_else(|e| panic!("create {target:?}: {e}"));
    let mut w = BufWriter::new(file);
    format::write_header(&mut w, &header).unwrap();
    w.flush().unwrap();
    for msg in rx {
        match msg {
            Msg::Decl { id, name, unit } => {
                format::write_decl(&mut w, id, &name, &unit).unwrap();
                w.flush().unwrap();
            }
            Msg::Frame(record) => {
                format::write_frame(&mut w, &record).unwrap();
                w.flush().unwrap();
            }
            Msg::Flush(reply) => {
                w.flush().unwrap();
                reply.send(()).unwrap();
            }
        }
    }
    tracing::info!("vor-record writer exiting");
}