ocl 0.19.7

OpenCL bindings and interfaces for Rust.
Documentation
// use std::sync::Arc;
// use std::sync::atomic::AtomicBool;
use crate::core::{ClNullEventPtr, Mem, MemMap as MemMapCore, OclPrm};
use crate::error::{Error as OclError, Result as OclResult};
use crate::r#async::MemMap;
use crate::{Event, EventList, Queue};
use futures::{Async, Future, Poll};

/// A future which resolves to a `MemMap` as soon as its creating command
/// completes.
///
/// [UNSTABLE]: This type's methods may be renamed or otherwise changed at any time.
#[must_use = "futures do nothing unless polled"]
#[derive(Debug)]
pub struct FutureMemMap<T: OclPrm> {
    core: Option<MemMapCore<T>>,
    len: usize,
    map_event: Event,
    unmap_wait_events: Option<EventList>,
    unmap_event: Option<Event>,
    buffer: Option<Mem>,
    queue: Option<Queue>,
    callback_is_set: bool,
    // buffer_is_mapped: Option<Arc<AtomicBool>>,
}

impl<T: OclPrm> FutureMemMap<T> {
    /// Returns a new `FutureMemMap`.
    pub unsafe fn new(
        core: MemMapCore<T>,
        len: usize,
        map_event: Event,
        buffer: Mem,
        queue: Queue,
        /*buffer_is_mapped: Arc<AtomicBool>*/
    ) -> FutureMemMap<T> {
        FutureMemMap {
            core: Some(core),
            len,
            map_event,
            unmap_wait_events: None,
            unmap_event: None,
            buffer: Some(buffer),
            queue: Some(queue),
            callback_is_set: false,
            // buffer_is_mapped: Some(buffer_is_mapped),
        }
    }

    /// Set an event wait list for the unmap command.
    ///
    /// Setting a wait list here will disallow any wait list from being set
    /// later if/when calling unmap manually.
    ///
    /// [UNSTABLE]: This method may be renamed or otherwise changed.
    pub fn set_unmap_wait_events<El>(&mut self, wait_events: El)
    where
        El: Into<EventList>,
    {
        self.unmap_wait_events = Some(wait_events.into())
    }

    /// Set an event wait list for the unmap command.
    ///
    /// See `::set_unmap_wait_events`.
    pub fn ewait_unmap<L: Into<EventList>>(mut self, wait_events: L) -> FutureMemMap<T> {
        self.set_unmap_wait_events(wait_events);
        self
    }

    /// Create an event which will be triggered (set complete) after this
    /// future resolves into a `MemMap` **and** after that `MemMap` is dropped
    /// or manually unmapped.
    ///
    /// The returned event can be added to the wait list of subsequent OpenCL
    /// commands with the expectation that when all preceeding futures are
    /// complete, the event will automatically be 'triggered' by having its
    /// status set to complete, causing those commands to execute. This can be
    /// used to inject host side code in amongst OpenCL commands without
    /// thread blocking or extra delays of any kind.
    ///
    /// [UNSTABLE]: This method may be renamed or otherwise changed.
    pub fn create_unmap_event(&mut self) -> OclResult<&mut Event> {
        if let Some(ref queue) = self.queue {
            let uev = Event::user(&queue.context())?;
            self.unmap_event = Some(uev);
            Ok(self.unmap_event.as_mut().unwrap())
        } else {
            Err("FutureMemMap::create_unmap_event: No queue found!".into())
        }
    }

    /// Specifies an event which will be triggered (set complete) after this
    /// future resolves into a `MemMap` **and** after that `MemMap` is dropped
    /// or manually unmapped.
    ///
    /// See `::create_unmap_event`.
    pub fn enew_unmap<En>(mut self, mut enew: En) -> FutureMemMap<T>
    where
        En: ClNullEventPtr,
    {
        {
            let unmap_event = self.create_unmap_event().expect("FutureMemMap::enew_unmap");
            unsafe {
                enew.clone_from(unmap_event);
            }
        }
        self
    }

    /// Specifies the queue to be used for the unmap command.
    pub fn set_unmap_queue(&mut self, queue: Queue) {
        self.queue = Some(queue)
    }

    /// Specifies the queue to be used for the unmap command.
    pub fn with_unmap_queue(mut self, queue: Queue) -> FutureMemMap<T> {
        self.set_unmap_queue(queue);
        self
    }

    /// Returns the unmap event if it has been created.
    ///
    /// [UNSTABLE]: This method may be renamed or otherwise changed.
    #[inline]
    pub fn unmap_event(&self) -> Option<&Event> {
        self.unmap_event.as_ref()
    }

    /// Blocks the current thread until the OpenCL command is complete and an
    /// appropriate lock can be obtained on the underlying data.
    pub fn wait(self) -> OclResult<MemMap<T>> {
        <Self as Future>::wait(self)
    }

    /// Resolves this `FutureMemMap` into a `MemMap`.
    fn to_mapped_mem(&mut self) -> OclResult<MemMap<T>> {
        match (self.core.take(), self.buffer.take(), self.queue.take()) {
            (Some(core), Some(buffer), Some(queue)) => {
                // TODO: Add `buffer_is_mapped` to list of joined stuff.
                unsafe {
                    Ok(MemMap::new(
                        core,
                        self.len,
                        self.unmap_wait_events.take(),
                        self.unmap_event.take(),
                        buffer,
                        queue,
                        /*self.buffer_is_mapped.take().unwrap()*/
                    ))
                }
            }
            _ => Err("FutureMemMap::create_unmap_event: No queue and/or buffer found!".into()),
        }
    }
}

#[cfg(not(feature = "async_block"))]
impl<T> Future for FutureMemMap<T>
where
    T: OclPrm + 'static,
{
    type Item = MemMap<T>;
    type Error = OclError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // println!("Polling FutureMemMap...");
        match self.map_event.is_complete() {
            Ok(true) => self.to_mapped_mem().map(|mm| Async::Ready(mm)),
            Ok(false) => {
                if !self.callback_is_set {
                    self.map_event.set_unpark_callback()?;
                    self.callback_is_set = true;
                }

                Ok(Async::NotReady)
            }
            Err(err) => Err(err.into()),
        }
    }
}

/// Blocking implementation.
#[cfg(feature = "async_block")]
impl<T: OclPrm> Future for FutureMemMap<T> {
    type Item = MemMap<T>;
    type Error = OclError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // println!("Polling FutureMemMap...");
        let _ = self.callback_is_set;
        self.map_event.wait_for()?;
        self.to_mapped_mem().map(|mm| Async::Ready(mm))
    }
}

unsafe impl<T: OclPrm> Send for FutureMemMap<T> {}
unsafe impl<T: OclPrm> Sync for FutureMemMap<T> {}