use crate::error::CudaResult;
use crate::ffi::{CU_EVENT_DEFAULT, CUevent};
use crate::loader::try_driver;
use crate::stream::Stream;
pub struct Event {
raw: CUevent,
}
unsafe impl Send for Event {}
impl Event {
pub fn new() -> CudaResult<Self> {
Self::with_flags(CU_EVENT_DEFAULT)
}
pub fn with_flags(flags: u32) -> CudaResult<Self> {
let api = try_driver()?;
let mut raw = CUevent::default();
crate::cuda_call!((api.cu_event_create)(&mut raw, flags))?;
Ok(Self { raw })
}
pub fn record(&self, stream: &Stream) -> CudaResult<()> {
let api = try_driver()?;
crate::cuda_call!((api.cu_event_record)(self.raw, stream.raw()))
}
pub fn query(&self) -> CudaResult<bool> {
let api = try_driver()?;
let rc = unsafe { (api.cu_event_query)(self.raw) };
if rc == 0 {
Ok(true)
} else if rc == crate::ffi::CUDA_ERROR_NOT_READY {
Ok(false)
} else {
Err(crate::error::CudaError::from_raw(rc))
}
}
pub fn synchronize(&self) -> CudaResult<()> {
let api = try_driver()?;
crate::cuda_call!((api.cu_event_synchronize)(self.raw))
}
pub fn elapsed_time(start: &Event, end: &Event) -> CudaResult<f32> {
let api = try_driver()?;
let mut ms: f32 = 0.0;
crate::cuda_call!((api.cu_event_elapsed_time)(&mut ms, start.raw, end.raw))?;
Ok(ms)
}
#[inline]
pub fn raw(&self) -> CUevent {
self.raw
}
}
impl Drop for Event {
fn drop(&mut self) {
if let Ok(api) = try_driver() {
let rc = unsafe { (api.cu_event_destroy_v2)(self.raw) };
if rc != 0 {
tracing::warn!(
cuda_error = rc,
event = ?self.raw,
"cuEventDestroy_v2 failed during drop"
);
}
}
}
}