use std::{
mem::{self, ManuallyDrop},
ops::{Deref, DerefMut},
ptr::null_mut,
};
use crate::{
error::CudaResult,
memory::{cuda_free_locked, cuda_malloc_locked, DeviceCopy},
};
#[derive(Debug)]
pub struct LockedBox<T: DeviceCopy> {
pub(crate) ptr: *mut T,
}
unsafe impl<T: Send + DeviceCopy> Send for LockedBox<T> {}
unsafe impl<T: Sync + DeviceCopy> Sync for LockedBox<T> {}
impl<T: DeviceCopy> LockedBox<T> {
pub unsafe fn uninitialized() -> CudaResult<Self> {
if mem::size_of::<T>() == 0 {
Ok(LockedBox { ptr: null_mut() })
} else {
let ptr = cuda_malloc_locked(1)?;
Ok(LockedBox { ptr })
}
}
pub fn new(val: &T) -> CudaResult<Self> {
unsafe {
let mut uninit = Self::uninitialized()?;
*uninit = *val;
Ok(uninit)
}
}
pub fn into_raw(self) -> *mut T {
ManuallyDrop::new(self).ptr
}
pub unsafe fn from_raw(ptr: *mut T) -> Self {
Self { ptr }
}
pub fn as_raw(&self) -> *mut T {
self.ptr
}
}
impl<T: DeviceCopy> Drop for LockedBox<T> {
fn drop(&mut self) {
if self.ptr.is_null() {
return;
}
unsafe {
let _ = cuda_free_locked(self.ptr);
}
}
}
impl<T: DeviceCopy> Deref for LockedBox<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr }
}
}
impl<T: DeviceCopy> DerefMut for LockedBox<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.ptr }
}
}