use crate::core::{
self, AsMem, ClNullEventPtr, ClWaitListPtr, Mem as MemCore, MemMap as MemMapCore, OclPrm,
};
use crate::error::Result as OclResult;
use crate::standard::{ClNullEventPtrEnum, ClWaitListPtrEnum, Event, EventList, Queue};
use std::ops::{Deref, DerefMut};
#[must_use = "commands do nothing unless enqueued"]
#[derive(Debug)]
pub struct MemUnmapCmd<'c, T>
where
T: 'c + OclPrm,
{
queue: Option<&'c Queue>,
mem_map: &'c mut MemMap<T>,
ewait: Option<ClWaitListPtrEnum<'c>>,
enew: Option<ClNullEventPtrEnum<'c>>,
}
impl<'c, T> MemUnmapCmd<'c, T>
where
T: OclPrm,
{
fn new(mem_map: &'c mut MemMap<T>) -> MemUnmapCmd<'c, T> {
MemUnmapCmd {
queue: None,
mem_map,
ewait: None,
enew: None,
}
}
pub fn queue<'q, Q>(mut self, queue: &'q Q) -> MemUnmapCmd<'c, T>
where
'q: 'c,
Q: 'q + AsRef<Queue>,
{
self.queue = Some(queue.as_ref());
self
}
pub fn ewait<Ewl>(mut self, ewait: Ewl) -> MemUnmapCmd<'c, T>
where
Ewl: Into<ClWaitListPtrEnum<'c>>,
{
self.ewait = Some(ewait.into());
self
}
pub fn enew<En>(mut self, enew: En) -> MemUnmapCmd<'c, T>
where
En: Into<ClNullEventPtrEnum<'c>>,
{
self.enew = Some(enew.into());
self
}
pub fn enq(self) -> OclResult<()> {
self.mem_map
.enqueue_unmap(self.queue, self.ewait, self.enew)
}
}
#[derive(Debug)]
pub struct MemMap<T>
where
T: OclPrm,
{
core: MemMapCore<T>,
len: usize,
buffer: MemCore,
queue: Queue,
unmap_wait_events: Option<EventList>,
unmap_event: Option<Event>,
is_unmapped: bool,
}
impl<T> MemMap<T>
where
T: OclPrm,
{
pub unsafe fn new(
core: MemMapCore<T>,
len: usize,
unmap_wait_events: Option<EventList>,
unmap_event: Option<Event>,
buffer: MemCore,
queue: Queue,
) -> MemMap<T> {
MemMap {
core,
len,
buffer,
queue,
unmap_wait_events,
unmap_event,
is_unmapped: false,
}
}
pub fn unmap<'c>(&'c mut self) -> MemUnmapCmd<'c, T> {
MemUnmapCmd::new(self)
}
pub fn enqueue_unmap<Ewl, En>(
&mut self,
queue: Option<&Queue>,
ewait_opt: Option<Ewl>,
mut enew_opt: Option<En>,
) -> OclResult<()>
where
En: ClNullEventPtr,
Ewl: ClWaitListPtr,
{
if !self.is_unmapped {
assert!(
!(ewait_opt.is_some() && self.unmap_wait_events.is_some()),
"MemMap::enqueue_unmap: Cannot set an event wait list for the unmap command \
when the 'unmap_wait_events' has already been set."
);
let mut origin_event_opt = if self.unmap_event.is_some() || enew_opt.is_some() {
Some(Event::empty())
} else {
None
};
core::enqueue_unmap_mem_object(
queue.unwrap_or(&self.queue),
&self.buffer,
&self.core,
ewait_opt.and(self.unmap_wait_events.as_ref()),
origin_event_opt.as_mut(),
)?;
self.is_unmapped = true;
if let Some(origin_event) = origin_event_opt {
if let Some(ref mut enew) = enew_opt {
unsafe { enew.clone_from(&origin_event) }
}
if let Some(unmap_user_event) = self.unmap_event.take() {
#[cfg(not(feature = "async_block"))]
unsafe {
origin_event.register_event_relay(unmap_user_event)?;
}
#[cfg(feature = "async_block")]
origin_event.wait_for()?;
#[cfg(feature = "async_block")]
unmap_user_event.set_complete()?;
}
}
Ok(())
} else {
Err("ocl_core::- ::unmap: Already unmapped.".into())
}
}
pub fn unmap_event(&self) -> Option<&Event> {
self.unmap_event.as_ref()
}
pub fn unmap_wait_events(&self) -> Option<&EventList> {
self.unmap_wait_events.as_ref()
}
#[inline]
pub fn is_unmapped(&self) -> bool {
self.is_unmapped
}
#[inline]
pub fn as_ptr(&self) -> *const T {
self.core.as_ptr()
}
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut T {
self.core.as_mut_ptr()
}
#[inline]
pub fn queue(&self) -> &Queue {
&self.queue
}
}
impl<T> Deref for MemMap<T>
where
T: OclPrm,
{
type Target = [T];
fn deref(&self) -> &[T] {
assert!(
!self.is_unmapped,
"Mapped memory has been unmapped and cannot be accessed."
);
unsafe { self.core.as_slice(self.len) }
}
}
impl<T> DerefMut for MemMap<T>
where
T: OclPrm,
{
fn deref_mut(&mut self) -> &mut [T] {
assert!(
!self.is_unmapped,
"Mapped memory has been unmapped and cannot be accessed."
);
unsafe { self.core.as_slice_mut(self.len) }
}
}
impl<T: OclPrm> Drop for MemMap<T> {
fn drop(&mut self) {
if !self.is_unmapped {
self.enqueue_unmap::<&Event, &mut Event>(None, None, None)
.ok();
}
}
}
impl<T: OclPrm> AsMem<T> for MemMap<T> {
fn as_mem(&self) -> &MemCore {
self.core.as_mem()
}
}