use super::{ProcessModeOverride, StatisticsRecorder};
#[derive(Debug, Clone)]
pub(crate) struct IssuedRecorder {
recorder: Option<StatisticsRecorder>,
}
impl IssuedRecorder {
pub(crate) fn new() -> Self {
Self {
recorder: ProcessModeOverride::active_recorder(),
}
}
pub(crate) fn apply<R>(&self, launch: impl FnOnce() -> R) -> R {
let previous = running::replace(Some(self.recorder.clone()));
let restore = Restore { previous };
let launched = launch();
core::mem::drop(restore);
launched
}
pub(crate) fn running() -> Option<Option<StatisticsRecorder>> {
running::get()
}
}
struct Restore {
previous: Option<Option<StatisticsRecorder>>,
}
impl Drop for Restore {
fn drop(&mut self) {
running::replace(self.previous.take());
}
}
#[cfg(feature = "std")]
mod running {
use super::StatisticsRecorder;
use core::cell::RefCell;
std::thread_local! {
static RUNNING: RefCell<Option<Option<StatisticsRecorder>>> = const { RefCell::new(None) };
}
pub(super) fn replace(
recorder: Option<Option<StatisticsRecorder>>,
) -> Option<Option<StatisticsRecorder>> {
RUNNING.with(|running| running.replace(recorder))
}
pub(super) fn get() -> Option<Option<StatisticsRecorder>> {
RUNNING.with(|running| running.borrow().clone())
}
}
#[cfg(not(feature = "std"))]
mod running {
use super::StatisticsRecorder;
use cubecl_environment::sync::Mutex;
static RUNNING: Mutex<Option<Option<StatisticsRecorder>>> = Mutex::new(None);
pub(super) fn replace(
recorder: Option<Option<StatisticsRecorder>>,
) -> Option<Option<StatisticsRecorder>> {
core::mem::replace(&mut *RUNNING.lock(), recorder)
}
pub(super) fn get() -> Option<Option<StatisticsRecorder>> {
RUNNING.lock().clone()
}
}
#[cfg(test)]
mod tests {
use super::super::{
KernelOutcome, KernelRegistration, ProcessMode, ProcessModeOverride, StatisticsCollector,
};
use super::*;
use alloc::vec;
#[test]
#[serial_test::serial]
fn a_launch_counts_where_it_was_issued() {
let issuing = StatisticsCollector::new();
let gathering = ProcessModeOverride::new(ProcessMode::CompileOnly, &issuing);
let issued = IssuedRecorder::new();
core::mem::drop(gathering);
let later = StatisticsCollector::new();
let tuning = ProcessModeOverride::new(ProcessMode::CompileAndAutotune, &later);
let registered = issued.apply(KernelRegistration::register);
let outside = IssuedRecorder { recorder: None }.apply(KernelRegistration::register);
core::mem::drop(tuning);
let settled = registered
.expect("issued under an override")
.settle(KernelOutcome::Compiled);
assert!(outside.is_none(), "issued under none, it counts nowhere");
assert_eq!(issuing.statistics().compilation.compiled, 1);
assert_eq!(later.statistics().compilation.registered, 0);
core::mem::drop(settled);
}
}