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}