use std::{
sync::mpsc,
thread,
time::{Duration, Instant},
};
use sysinfo::UpdateKind;
use hwloc2;
use log::*;
use simplelog;
use clap::Parser;
use std::fs::File;
mod util;
mod system;
mod uistate;
mod ordered_core_selections;
mod strings;
mod shortcuts;
mod uifrontend;
#[cfg(feature = "gui")]
mod eguifrontend;
#[cfg(feature = "tui")]
mod ratatuifrontend;
mod cpumap;
mod topologycache;
use cpumap::CPUMap;
use cpumap::Event;
use uifrontend::UIFrontendType;
fn start_tick_thread(tick_period: Duration) -> mpsc::Receiver<Event> {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let mut last_tick = Instant::now();
loop {
thread::sleep(tick_period / 10);
if last_tick.elapsed() >= tick_period && tx.send(Event::Tick).is_ok() {
last_tick = Instant::now();
}
}
});
rx
}
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
#[arg(short, long, default_value_t = false)]
tui: bool,
#[arg(short, long, default_value_t = simplelog::LevelFilter::Info)]
log: simplelog::LevelFilter,
#[clap(short, long, value_parser = |secs: &str| secs.parse().map(Duration::from_millis), default_value = "5000")]
update: Duration,
}
fn main() -> anyhow::Result<()> {
let args = Args::parse();
let log_file = File::create("cpumap.log").expect("Could not create log file `cpumap.log`");
_ = simplelog::WriteLogger::init(args.log, simplelog::Config::default(), log_file);
info!("logging initialized");
let event_rx = start_tick_thread(args.update);
let mut sys = sysinfo::System::new();
sys.refresh_processes_specifics(
sysinfo::ProcessRefreshKind::new().with_cmd(UpdateKind::OnlyIfNotSet)
.with_exe(UpdateKind::OnlyIfNotSet));
sys.refresh_cpu();
let topo = hwloc2::Topology::new().unwrap();
let frontend_type = if cfg!(feature = "gui") && cfg!(feature = "tui") {
if args.tui { UIFrontendType::Ratatui } else { UIFrontendType::Egui }
} else if cfg!(feature = "gui") {
UIFrontendType::Egui
} else if cfg!(feature = "tui") {
UIFrontendType::Ratatui
} else {
panic!("cpumap must be built with either `gui` or `tui` feature");
};
CPUMap::new(topo, sys, event_rx, frontend_type).run()
}