use crate::bitmasks::event::EventTypes;
use crate::enums::event::XidError;
use crate::error::{NvmlError, NvmlErrorWithSource};
use crate::struct_wrappers::event::EventData;
use crate::Device;
use crate::EventSet;
use crate::Nvml;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Debug)]
pub enum Event<'nvml> {
ClockChange(Device<'nvml>),
CriticalXidError(Device<'nvml>, XidError),
DoubleBitEccError(Device<'nvml>),
PowerStateChange(Device<'nvml>),
SingleBitEccError(Device<'nvml>),
Unknown,
}
impl<'nvml> From<EventData<'nvml>> for Event<'nvml> {
fn from(struct_: EventData<'nvml>) -> Self {
if struct_.event_type.contains(EventTypes::CLOCK_CHANGE) {
Event::ClockChange(struct_.device)
} else if struct_.event_type.contains(EventTypes::CRITICAL_XID_ERROR) {
Event::CriticalXidError(struct_.device, struct_.event_data.unwrap())
} else if struct_
.event_type
.contains(EventTypes::DOUBLE_BIT_ECC_ERROR)
{
Event::DoubleBitEccError(struct_.device)
} else if struct_.event_type.contains(EventTypes::PSTATE_CHANGE) {
Event::PowerStateChange(struct_.device)
} else if struct_
.event_type
.contains(EventTypes::SINGLE_BIT_ECC_ERROR)
{
Event::SingleBitEccError(struct_.device)
} else {
Event::Unknown
}
}
}
pub struct EventLoop<'nvml> {
set: EventSet<'nvml>,
}
impl<'nvml> EventLoop<'nvml> {
pub fn register_device(
mut self,
device: &'nvml Device<'nvml>,
) -> Result<Self, NvmlErrorWithSource> {
self.set = device.register_events(device.supported_event_types()?, self.set)?;
Ok(self)
}
pub fn run_forever<F>(&mut self, mut callback: F)
where
F: FnMut(Result<Event<'nvml>, NvmlError>, &mut EventLoopState),
{
let mut state = EventLoopState { interrupted: false };
loop {
if state.interrupted {
break;
};
match self.set.wait(1) {
Ok(data) => {
callback(Ok(data.into()), &mut state);
}
Err(NvmlError::Timeout) => continue,
value => callback(value.map(|d| d.into()), &mut state),
};
}
}
pub fn as_inner(&'nvml self) -> &'nvml EventSet<'nvml> {
&(self.set)
}
pub fn as_mut_inner(&'nvml mut self) -> &'nvml mut EventSet<'nvml> {
&mut (self.set)
}
pub fn into_inner(self) -> EventSet<'nvml> {
self.set
}
}
impl<'nvml> From<EventSet<'nvml>> for EventLoop<'nvml> {
fn from(set: EventSet<'nvml>) -> Self {
Self { set }
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct EventLoopState {
interrupted: bool,
}
impl EventLoopState {
pub fn interrupt(&mut self) {
self.interrupted = true;
}
}
pub trait EventLoopProvider {
fn create_event_loop<'nvml>(
&'nvml self,
devices: Vec<&'nvml Device<'nvml>>,
) -> Result<EventLoop, NvmlErrorWithSource>;
}
impl EventLoopProvider for Nvml {
fn create_event_loop<'nvml>(
&'nvml self,
devices: Vec<&Device<'nvml>>,
) -> Result<EventLoop, NvmlErrorWithSource> {
let mut set = self.create_event_set()?;
for d in devices {
set = d.register_events(d.supported_event_types()?, set)?;
}
Ok(EventLoop { set })
}
}