1use std::fmt;
2use std::iter::Iterator;
3use std::mem::ManuallyDrop;
4
5use crate::ffi::cl_device_id;
6use crate::ll::{ClContext, ClDeviceID, ContextProperties, ContextPtr, DevicePtr, VecOrSlice};
7
8use crate::{Device, Output};
9
10pub struct Context {
11 inner: ManuallyDrop<ClContext>,
12 _devices: ManuallyDrop<Vec<ClDeviceID>>,
13 _unconstructable: (),
14}
15
16impl Context {
17 pub fn build<'a, D>(obj: ClContext, devices: D) -> Context
21 where
22 D: Into<VecOrSlice<'a, Device>>,
23 {
24 let devices = devices.into();
25 let ll_devices = devices
26 .as_slice()
27 .iter()
28 .map(|d| d.low_level_device().clone())
29 .collect();
30 Context {
31 inner: ManuallyDrop::new(obj),
32 _devices: ManuallyDrop::new(ll_devices),
33 _unconstructable: (),
34 }
35 }
36
37 pub fn low_level_context(&self) -> &ClContext {
38 &*self.inner
39 }
40
41 pub fn from_low_level_context(ll_context: &ClContext) -> Output<Context> {
42 let ll_devices = unsafe { ll_context.devices() }?;
43 let devices: Vec<Device> = ll_devices.into_iter().map(|d| Device::new(d)).collect();
44 Ok(Context::build(ll_context.clone(), devices))
45 }
46
47 pub fn create<'a, D: Into<VecOrSlice<'a, Device>>>(devices: D) -> Output<Context> {
48 let devices = devices.into();
49 let device_ptrs: Vec<cl_device_id> =
50 devices.iter().map(|d| unsafe { d.device_ptr() }).collect();
51
52 let ll_context: ClContext = unsafe { ClContext::create(&device_ptrs[..]) }?;
53 Ok(Context::build(ll_context, devices))
54 }
55
56 pub fn devices(&self) -> &[ClDeviceID] {
57 &self._devices[..]
58 }
59
60 pub fn reference_count(&self) -> Output<u32> {
61 unsafe { self.inner.reference_count() }
62 }
63
64 pub fn properties(&self) -> Output<Vec<ContextProperties>> {
65 unsafe { self.inner.properties() }
66 }
67
68 pub fn num_devices(&self) -> usize {
69 self._devices.len()
70 }
71}
72
73impl Clone for Context {
74 fn clone(&self) -> Context {
75 let cloned_devices = self._devices.iter().map(Clone::clone).collect();
76 Context {
77 inner: ManuallyDrop::new((*self.inner).clone()),
78 _devices: ManuallyDrop::new(cloned_devices),
79 _unconstructable: (),
80 }
81 }
82}
83
84impl Drop for Context {
85 fn drop(&mut self) {
86 unsafe { ManuallyDrop::drop(&mut self.inner) }
87 }
88}
89
90unsafe impl Send for Context {}
95unsafe impl Sync for Context {}
96
97impl PartialEq for Context {
98 fn eq(&self, other: &Self) -> bool {
99 *self.inner == *other.inner
100 }
101}
102
103impl Eq for Context {}
104
105impl fmt::Debug for Context {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 write!(f, "Context{{{:?}}}", unsafe { self.inner.context_ptr() })
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::Context;
114 use crate::device::Device;
115 use crate::testing;
116
117 #[test]
118 fn context_can_be_created_via_a_device() {
119 let device: Device = testing::get_device();
120 let devices = vec![device];
121 let _context: Context =
122 Context::create(&devices[..]).expect("Failed to create context from a device");
123 }
124
125 #[test]
126 fn context_ptr_is_implemented() {
127 let ctx = testing::get_context();
128 ctx.reference_count().unwrap();
129 ctx.num_devices();
130 ctx.properties().unwrap();
131 }
132}