1use objc2::rc::Retained;
4use objc2::runtime::ProtocolObject;
5use objc2_metal::{MTLDevice, MTLSharedEvent};
6
7use super::Device;
8use crate::{GpuError, Result};
9
10const SPIN: std::time::Duration = std::time::Duration::from_micros(50);
12
13pub struct Event {
17 raw: Retained<ProtocolObject<dyn MTLSharedEvent>>,
18}
19
20unsafe impl Send for Event {}
23unsafe impl Sync for Event {}
25
26impl Event {
27 pub fn new(device: &Device) -> Result<Self> {
29 let raw = device
30 .raw()
31 .newSharedEvent()
32 .ok_or_else(|| GpuError::CommandBuffer("cannot create a shared event".into()))?;
33 Ok(Self { raw })
34 }
35
36 pub fn signal(&self, value: u64) {
38 self.raw.setSignaledValue(value);
39 }
40
41 pub fn wait(&self, value: u64, timeout: std::time::Duration) -> bool {
44 let spin = std::time::Instant::now();
45 while spin.elapsed() < SPIN.min(timeout) {
46 if self.value() >= value {
47 return true;
48 }
49 std::hint::spin_loop();
50 }
51 let ms = timeout.saturating_sub(SPIN).as_millis().max(1) as u64;
52 self.raw.waitUntilSignaledValue_timeoutMS(value, ms)
53 }
54
55 pub fn value(&self) -> u64 {
57 self.raw.signaledValue()
58 }
59
60 pub(crate) fn raw(&self) -> &ProtocolObject<dyn MTLSharedEvent> {
61 &self.raw
62 }
63}
64
65impl std::fmt::Debug for Event {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 f.debug_struct("Event")
68 .field("value", &self.value())
69 .finish()
70 }
71}