use crate::error::{LibraryError, check_cuvs};
use std::ffi::CString;
use std::io::{Write, stderr};
use std::path::Path;
use std::time::Duration;
type Result<T> = std::result::Result<T, ResourcesError>;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum ResourcesError {
#[error(transparent)]
Library(#[from] LibraryError),
#[error("CSV path contains an interior NUL byte")]
InvalidPath(#[from] std::ffi::NulError),
}
#[derive(Debug)]
pub struct Resources {
handle: ffi::cuvsResources_t,
}
impl Resources {
pub fn new() -> Result<Resources> {
let mut handle: ffi::cuvsResources_t = 0;
check_cuvs(unsafe { ffi::cuvsResourcesCreate(&mut handle) })?;
Ok(Resources { handle })
}
pub fn with_memory_tracking(
csv_path: impl AsRef<Path>,
sample_interval: Option<Duration>,
) -> Result<Resources> {
let c_path = CString::new(csv_path.as_ref().as_os_str().as_encoded_bytes())?;
let sample_interval_ms =
sample_interval.unwrap_or(Duration::from_millis(10)).as_millis() as i64;
let mut handle: ffi::cuvsResources_t = 0;
check_cuvs(unsafe {
ffi::cuvsResourcesCreateWithMemoryTracking(
&mut handle,
c_path.as_ptr(),
sample_interval_ms,
)
})?;
Ok(Resources { handle })
}
pub unsafe fn with_stream(stream: ffi::cudaStream_t) -> Result<Resources> {
let res = Resources::new()?;
check_cuvs(unsafe { ffi::cuvsStreamSet(res.handle, stream) })?;
Ok(res)
}
pub fn stream(&self) -> Result<ffi::cudaStream_t> {
unsafe {
let mut stream = std::mem::MaybeUninit::<ffi::cudaStream_t>::uninit();
check_cuvs(ffi::cuvsStreamGet(self.handle, stream.as_mut_ptr()))?;
Ok(stream.assume_init())
}
}
pub fn sync_stream(&self) -> Result<()> {
check_cuvs(unsafe { ffi::cuvsStreamSync(self.handle) })?;
Ok(())
}
pub(crate) fn handle(&self) -> ffi::cuvsResources_t {
self.handle
}
}
impl Drop for Resources {
fn drop(&mut self) {
if let Err(e) = check_cuvs(unsafe { ffi::cuvsResourcesDestroy(self.handle) }) {
write!(stderr(), "failed to call cuvsResourcesDestroy {:?}", e)
.expect("failed to write to stderr");
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_resources_create() {
let _ = Resources::new();
}
}