use crate::{named,
non_named::{self, InitOnce},
SemaphoreRef};
use core::{cell::UnsafeCell,
ffi::c_uint,
fmt::{self, Display, Formatter},
pin::Pin};
#[must_use]
#[derive(Debug)]
pub struct Semaphore {
inner: UnsafeCell<Option<named::Semaphore>>,
init_once: InitOnce,
}
unsafe impl Sync for Semaphore {}
impl Semaphore {
#[inline]
pub const fn uninit() -> Self {
Self { inner: UnsafeCell::new(None), init_once: InitOnce::new() }
}
}
impl non_named::Sealed for Semaphore {}
impl non_named::Semaphore for Semaphore {
#[inline]
#[allow(clippy::unwrap_in_result)]
fn init_with(self: Pin<&Self>, sem_count: c_uint) -> Result<SemaphoreRef<'_>, bool> {
let r = self.init_once.call_once(|| {
named::Semaphore::anonymous_with(sem_count).map(|sem| {
let inner_exclusive = unsafe { &mut *self.inner.get() };
*inner_exclusive = Some(sem);
})
});
match r {
#[allow(clippy::expect_used)]
Some(Ok(())) => Ok(self.sem_ref().expect("the `Semaphore` is ready")),
Some(Err(())) => Err(false),
None => Err(true),
}
}
#[inline]
#[allow(clippy::unwrap_in_result)]
fn sem_ref(self: Pin<&Self>) -> Result<SemaphoreRef<'_>, ()> {
if self.init_once.is_ready() {
let inner_shared = unsafe { &*self.inner.get() };
#[allow(clippy::expect_used)]
Ok(inner_shared
.as_ref()
.map(named::Semaphore::sem_ref)
.expect("always `Some` once initialized"))
} else {
Err(())
}
}
}
impl Default for Semaphore {
#[inline]
fn default() -> Self { Self::uninit() }
}
impl Display for Semaphore {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
use crate::non_named::Semaphore as _;
Pin::new(self).display().fmt(f)
}
}
impl Drop for Semaphore {
#[inline]
fn drop(&mut self) {
if let Some(sem) = self.inner.get_mut().take() {
let r = unsafe { sem.close() };
debug_assert!(r.is_ok(), "the semaphore is valid");
}
}
}
#[cfg(doctest)]
mod compile_fail_tests {
fn lifetime_enforced() {}
}