use crate::device_events::{Event, EventApi};
#[cfg(multi_threading)]
use crate::memory_management::drop_queue;
use crate::server::ServerError;
pub struct EventFence<A: EventApi> {
event: Result<Option<Event<A>>, ServerError>,
}
impl<A: EventApi> EventFence<A> {
pub fn new(stream: A::Stream) -> Self {
let event = match Event::new().and_then(|event| event.record(stream).map(|()| event)) {
Ok(event) => Ok(Some(event)),
Err(err) => {
log::warn!(
"a fence could not be recorded, synchronizing its stream instead: {err}"
);
A::stream_synchronize(stream)
.map(|()| None)
.map_err(Into::into)
}
};
Self { event }
}
pub fn wait_sync(self) -> Result<(), ServerError> {
match self.event? {
Some(event) => Ok(event.wait()?),
None => Ok(()),
}
}
pub fn wait_async(self, stream: A::Stream) -> Result<(), ServerError> {
let Some(event) = self.event? else {
return Ok(());
};
if let Err(err) = event.wait_async(stream) {
log::warn!("a stream could not be made to wait on a fence, waiting on the host: {err}");
event.wait()?;
}
Ok(())
}
}
impl<A: EventApi> core::fmt::Debug for EventFence<A> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}Fence", A::BACKEND)
}
}
#[cfg(multi_threading)]
impl<A: EventApi> drop_queue::Fence for EventFence<A> {
fn wait(self) -> Result<(), ServerError> {
self.wait_sync()
}
}