open_cl_low_level/
cl_pointer.rs

1use std::fmt;
2use std::marker::PhantomData;
3
4use crate::ffi::cl_bool;
5use crate::strings;
6
7/// ClPointer is a very short-lived struct that is used to homogenize the returns from
8/// many of the CL API calls. If a call to an OpenCL C function successfully returns
9/// a ClPointer that ClPointer MUST BE CONSUMED; Failure to consume the ClPointer will
10/// lead to a panic when the ClPointer struct is dropped.
11#[repr(C)]
12pub struct ClPointer<T: Copy> {
13    count: usize,
14    ptr: *mut T,
15    phantom: PhantomData<T>,
16    is_consumed: bool,
17}
18
19/// Only u8 ClPointers can become String
20impl ClPointer<u8> {
21    pub unsafe fn into_string(self) -> String {
22        strings::to_utf8_string(self.into_vec())
23    }
24}
25
26impl From<ClPointer<u8>> for String {
27    fn from(p: ClPointer<u8>) -> String {
28        strings::to_utf8_string(unsafe { p.into_vec() })
29    }
30}
31
32impl From<ClPointer<cl_bool>> for bool {
33    fn from(p: ClPointer<cl_bool>) -> bool {
34        match unsafe { p.into_one() } {
35            0 => false,
36            1 => true,
37            invalid_cl_bool => panic!("cl_bool was neither 0 nor 1: {:?}", invalid_cl_bool),
38        }
39    }
40}
41
42impl<T: Copy> ClPointer<T> {
43    pub unsafe fn new(count: usize, ptr: *mut T) -> ClPointer<T> {
44        ClPointer {
45            count,
46            ptr,
47            phantom: PhantomData,
48            is_consumed: false,
49        }
50    }
51
52    pub unsafe fn from_vec(mut v: Vec<T>) -> ClPointer<T> {
53        let ptr = v.as_mut_ptr();
54        let count = v.len();
55        std::mem::forget(v);
56        ClPointer::new(count, ptr)
57    }
58
59    pub unsafe fn new_empty() -> ClPointer<T> {
60        let mut v = vec![];
61        let ptr = v.as_mut_ptr();
62        std::mem::forget(v);
63        ClPointer::new(0, ptr)
64    }
65
66    pub fn is_empty(&self) -> bool {
67        self.count == 0
68    }
69
70    pub fn is_null(&self) -> bool {
71        self.ptr.is_null()
72    }
73
74    #[inline]
75    pub unsafe fn into_one(self) -> T {
76        self.ptr_cannot_be_null();
77        self.count_must_be_one();
78        let owned_ptr = self.ptr.to_owned();
79        std::mem::forget(self);
80        *owned_ptr
81    }
82
83    #[inline]
84    pub unsafe fn into_vec(self) -> Vec<T> {
85        self.ptr_cannot_be_null();
86        let many = Vec::from_raw_parts(self.ptr, self.count, self.count);
87        std::mem::forget(self);
88        many
89    }
90
91    #[inline]
92    fn ptr_cannot_be_null(&self) {
93        if self.ptr.is_null() {
94            panic!("Consumed cl_pointer was a null pointer {:?}", self);
95        }
96    }
97
98    #[inline]
99    fn count_must_be_one(&self) {
100        match self.count {
101            1 => (),
102            0 => {
103                panic!("cl_pointer was not 1 count: {:?}", self);
104            }
105            _ => {
106                panic!("cl_pointer was not 1 count: {:?}", self);
107            }
108        }
109    }
110}
111
112impl<T: Copy> Drop for ClPointer<T> {
113    fn drop(&mut self) {
114        panic_once!("An unconsumed ClPointer was allowed to drop. This would lead to a memory leak. All ClPointers must be consumed. {:?}", self);
115    }
116}
117
118impl<T: Copy> fmt::Debug for ClPointer<T> {
119    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
120        write!(
121            f,
122            "ClPointer<[ptr: {:?}, count: {:?}, size_of_t: {:?}, is_consumed: {:?}]>",
123            self.ptr,
124            self.count,
125            std::mem::size_of::<T>(),
126            self.is_consumed
127        )
128    }
129}