use std::sync::{Arc, Condvar, Mutex};
use std::time::{Duration, Instant};
use pyo3::prelude::*;
use running_process_core::pty::{IdleDetectorCore, IdleMonitorState};
use crate::signal_bool::NativeSignalBool;
#[pyclass]
pub(crate) struct NativeIdleDetector {
pub(crate) core: Arc<IdleDetectorCore>,
}
#[pymethods]
impl NativeIdleDetector {
#[new]
#[allow(clippy::too_many_arguments)]
#[pyo3(signature = (timeout_seconds, stability_window_seconds, sample_interval_seconds, enabled_signal, reset_on_input=true, reset_on_output=true, count_control_churn_as_output=true, initial_idle_for_seconds=0.0))]
pub(crate) fn new(
py: Python<'_>,
timeout_seconds: f64,
stability_window_seconds: f64,
sample_interval_seconds: f64,
enabled_signal: Py<NativeSignalBool>,
reset_on_input: bool,
reset_on_output: bool,
count_control_churn_as_output: bool,
initial_idle_for_seconds: f64,
) -> Self {
let now = Instant::now();
let initial_idle_for_seconds = initial_idle_for_seconds.max(0.0);
let last_reset_at = now
.checked_sub(Duration::from_secs_f64(initial_idle_for_seconds))
.unwrap_or(now);
let enabled = enabled_signal.borrow(py).value.clone();
Self {
core: Arc::new(IdleDetectorCore {
timeout_seconds,
stability_window_seconds,
sample_interval_seconds,
reset_on_input,
reset_on_output,
count_control_churn_as_output,
enabled,
state: Mutex::new(IdleMonitorState {
last_reset_at,
returncode: None,
interrupted: false,
}),
condvar: Condvar::new(),
}),
}
}
#[getter]
pub(crate) fn enabled(&self) -> bool {
self.core.enabled()
}
#[setter]
pub(crate) fn set_enabled(&self, enabled: bool) {
self.core.set_enabled(enabled);
}
pub(crate) fn record_input(&self, byte_count: usize) {
self.core.record_input(byte_count);
}
pub(crate) fn record_output(&self, data: &[u8]) {
self.core.record_output(data);
}
pub(crate) fn mark_exit(&self, returncode: i32, interrupted: bool) {
self.core.mark_exit(returncode, interrupted);
}
#[pyo3(signature = (timeout=None))]
pub(crate) fn wait(
&self,
py: Python<'_>,
timeout: Option<f64>,
) -> (bool, String, f64, Option<i32>) {
py.allow_threads(|| self.core.wait(timeout))
}
}