kithara-platform 0.0.1-alpha5

Cross-platform primitives (sync, time, thread) for native and wasm32.
Documentation
use std::{
    cell::Cell,
    time::{Duration, Instant},
};

use cpu_time::ThreadTime;

thread_local! {
    static SNAPSHOT: Cell<Option<(ThreadTime, Instant)>> = const { Cell::new(None) };
}

#[cfg(test)]
thread_local! {
    static SNAPSHOT_REFRESH_COUNT: Cell<u32> = const { Cell::new(0) };
}

#[cfg(test)]
thread_local! {
    static FORCED_CPU_ELAPSED: Cell<Option<Duration>> = const { Cell::new(None) };
}

pub(super) fn snapshot(now: Instant) -> Option<ThreadTime> {
    const SNAPSHOT_MAX_AGE: Duration = Duration::from_millis(1);

    SNAPSHOT.with(|snapshot| {
        if let Some((cpu, sampled_at)) = snapshot.get() {
            if now
                .checked_duration_since(sampled_at)
                .is_some_and(|age| age < SNAPSHOT_MAX_AGE)
            {
                return Some(cpu);
            }
        }

        if let Ok(cpu) = ThreadTime::try_now() {
            #[cfg(test)]
            SNAPSHOT_REFRESH_COUNT.with(|count| count.set(count.get() + 1));
            snapshot.set(Some((cpu, now)));
            return Some(cpu);
        }

        snapshot.set(None);
        None
    })
}

pub(super) fn thread_cpu_elapsed(start: Option<ThreadTime>) -> Option<Duration> {
    #[cfg(test)]
    {
        if let Some(cpu) = FORCED_CPU_ELAPSED.with(Cell::get) {
            return Some(cpu);
        }
    }

    start.and_then(|s| s.try_elapsed().ok())
}

#[cfg(test)]
pub(crate) fn force_cpu_elapsed(cpu: Option<Duration>) {
    FORCED_CPU_ELAPSED.with(|forced| forced.set(cpu));
}

#[cfg(test)]
pub(crate) fn snapshot_refresh_count() -> u32 {
    SNAPSHOT_REFRESH_COUNT.with(Cell::get)
}

#[cfg(test)]
pub(crate) fn force_snapshot_refresh_count(refresh_count: u32) {
    SNAPSHOT.with(|snapshot| snapshot.set(None));
    SNAPSHOT_REFRESH_COUNT.with(|count| count.set(refresh_count));
}