use std::{mem::MaybeUninit, sync::Arc};
use maudio_sys::ffi as sys;
use crate::{Binding, MaResult};
#[derive(Clone)]
pub struct Fence {
inner: Arc<FenceInner>,
}
unsafe impl Send for FenceInner {}
unsafe impl Sync for FenceInner {}
struct FenceInner {
inner: *mut sys::ma_fence,
}
impl Binding for Fence {
type Raw = *mut sys::ma_fence;
fn from_ptr(raw: Self::Raw) -> Self {
Self {
inner: Arc::new(FenceInner { inner: raw }),
}
}
fn to_raw(&self) -> Self::Raw {
self.inner.inner
}
}
#[must_use]
pub struct FenceGuard {
inner: Fence,
active: bool,
}
impl Fence {
pub fn new() -> MaResult<Fence> {
let mut mem: Box<std::mem::MaybeUninit<sys::ma_fence>> = Box::new(MaybeUninit::uninit());
fence_ffi::ma_fence_init(mem.as_mut_ptr())?;
let inner: *mut sys::ma_fence = Box::into_raw(mem) as *mut sys::ma_fence;
Ok(Fence::from_ptr(inner))
}
pub fn acquire(&self) -> MaResult<FenceGuard> {
fence_ffi::ma_fence_acquire(self.clone())?;
Ok(FenceGuard {
inner: self.clone(),
active: true,
})
}
fn release(&self) -> MaResult<()> {
fence_ffi::ma_fence_release(self.clone())
}
pub fn wait(&self) -> MaResult<()> {
fence_ffi::ma_fence_wait(self.clone())
}
}
pub(crate) mod fence_ffi {
use maudio_sys::ffi as sys;
use crate::{util::fence::Fence, Binding, MaResult, MaudioError};
pub fn ma_fence_init(fence: *mut sys::ma_fence) -> MaResult<()> {
let res = unsafe { sys::ma_fence_init(fence) };
MaudioError::check(res)
}
pub fn ma_fence_uninit(fence: Fence) {
unsafe {
sys::ma_fence_uninit(fence.to_raw());
}
}
pub fn ma_fence_acquire(fence: Fence) -> MaResult<()> {
let res = unsafe { sys::ma_fence_acquire(fence.to_raw()) };
MaudioError::check(res)
}
pub fn ma_fence_release(fence: Fence) -> MaResult<()> {
let res = unsafe { sys::ma_fence_release(fence.to_raw()) };
MaudioError::check(res)
}
pub fn ma_fence_wait(fence: Fence) -> MaResult<()> {
let res = unsafe { sys::ma_fence_wait(fence.to_raw()) };
MaudioError::check(res)
}
}
impl Drop for Fence {
fn drop(&mut self) {
fence_ffi::ma_fence_uninit(self.clone());
drop(unsafe { Box::from_raw(self.to_raw()) });
}
}
impl Drop for FenceGuard {
fn drop(&mut self) {
if self.active {
let _ = self.inner.release();
}
}
}