open_cl_low_level/
waitlist.rs

1use std::convert::TryInto;
2
3use crate::ffi::{clWaitForEvents, cl_event};
4use crate::{
5    build_output,
6    ClEvent,
7    EventPtr, // Error, EventPtr, cl_release_event,
8    Output,
9};
10
11/// The low-level function for synchronously waiting events (blocks the calling thread).
12///
13/// # Safety
14/// Due to call to OpenCL's FFI with raw pointer (or slice of raw pointers) this call will cause
15/// undefined behavior if any of the events is not in correct state, if the context of the events
16/// has been freed, if any of the events is a null pointer, if the queue the event was created with
17/// is freed, and a plethora of other conditions.
18pub unsafe fn cl_wait_for_events<'a>(wl: &'a [cl_event]) -> Output<()> {
19    build_output((), clWaitForEvents(wl.waitlist_len(), wl.waitlist_ptr()))
20}
21
22/// The low level trait for synchronously waiting for events.
23///
24/// # Safety
25/// Due to multiple dangerous memory safety concerns with using events this
26/// trait and it's functions are all unsafe. Mismanagement of the reference count,
27/// lifetime, context, or resuse of an event is undefined behavior.
28pub unsafe trait Waitlist: Sized {
29    /// Copies the waitlist's (self) events into the passed mutable vector.
30    ///
31    /// # Safety
32    /// Due to the movement of cl_event from one container to another, this function is unsafe
33    /// failure to correctly track reference counts of cl_event objects can lead to memory leaks and/or
34    /// segfaults.
35    ///
36    /// Note: When the vec that the events are given to Drops these events will not be released.
37    unsafe fn fill_waitlist(&self, wl: &mut Vec<cl_event>);
38
39    /// Consumes the waitlist into a vector of cl_events.
40    ///
41    /// # Safety
42    /// Due to the movement of cl_event from one container to another, this function is unsafe
43    /// failure to correctly track reference counts of cl_event objects can lead to memory leaks and/or
44    /// segfaults.
45    ///
46    /// Note: When the vec that the events are given to Drops these events will not be released.
47    unsafe fn new_waitlist(&self) -> Vec<cl_event>;
48
49    /// Synchronously waits (blocks the thread) until all events in the waitlist are complete.
50    ///
51    /// # Safety
52    /// Due to call to OpenCL's FFI with raw pointer (or Vec of raw pointers) this call will cause
53    /// undefined behavior if any of the events is not in correct state, if the context of the events
54    /// has been freed, if any of the events is a null pointer, if the queue the event was created with
55    /// is freed, and a plethora of other conditions.
56    ///
57    /// Note: When the vec that the events are given to Drops these events will not be released.
58    unsafe fn wait(self) -> Output<()> {
59        let mut waitlist = Vec::new();
60        self.fill_waitlist(&mut waitlist);
61        cl_wait_for_events(&waitlist[..])
62    }
63}
64
65/// This trait is used to produce the required size and pointer arguments to the FFI of OpenCL
66/// allowing for the synchronously waiting of a given event before execution is allowed to proceed.
67///
68/// # Safety
69/// Due to this trait and it's only function involving the use of raw pointers this trait is unsafe.
70/// Passing an event that has already been waited to OpenC is undefined behavior.
71pub unsafe trait WaitlistSizeAndPtr<'a>: Sized {
72    /// This function returns a const pointer to a cl_event.
73    ///
74    /// # Safety
75    /// Due to thisfunction involving the use of raw pointers this trait is unsafe.
76    /// Passing an event that has already been waited to OpenC is undefined behavior.
77    unsafe fn waitlist_len(&self) -> u32;
78    unsafe fn waitlist_ptr(&self) -> *const cl_event;
79
80}
81
82unsafe impl<'a> WaitlistSizeAndPtr<'a> for &'a [cl_event] {
83    unsafe fn waitlist_len(&self) -> u32 {
84        self.len().try_into().unwrap()
85    }
86
87    unsafe fn waitlist_ptr(&self) -> *const cl_event {
88        match self.len() {
89            0 => std::ptr::null() as *const cl_event,
90            _ => *self as *const _ as *const cl_event,
91        }
92    }
93}
94
95unsafe impl Waitlist for &[cl_event] {
96    unsafe fn fill_waitlist(&self, wait_list: &mut Vec<cl_event>) {
97        wait_list.extend_from_slice(self);
98    }
99
100    unsafe fn new_waitlist(&self) -> Vec<cl_event> {
101        self.to_vec()
102    }
103}
104
105unsafe impl Waitlist for &[ClEvent] {
106    unsafe fn fill_waitlist(&self, wait_list: &mut Vec<cl_event>) {
107        let waitlist = self.new_waitlist();
108        wait_list.extend(waitlist);
109    }
110
111    unsafe fn new_waitlist(&self) -> Vec<cl_event> {
112        self.iter().map(|evt| evt.event_ptr()).collect()
113    }
114}
115
116unsafe impl Waitlist for &ClEvent {
117    unsafe fn fill_waitlist(&self, wait_list: &mut Vec<cl_event>) {
118        wait_list.push(self.event_ptr());
119    }
120
121    unsafe fn new_waitlist(&self) -> Vec<cl_event> {
122        vec![self.event_ptr()]
123    }
124}
125
126unsafe impl<W: Waitlist> Waitlist for Option<W> {
127    unsafe fn fill_waitlist(&self, wait_list: &mut Vec<cl_event>) {
128        match self {
129            None => (),
130            Some(event) => event.fill_waitlist(wait_list),
131        }
132    }
133
134    unsafe fn new_waitlist(&self) -> Vec<cl_event> {
135        match self {
136            None => vec![],
137            Some(event) => event.new_waitlist(),
138        }
139    }
140}