use crate::{
alloc::CBox,
core::{optional::NSTDOptional, result::NSTDResult},
heap_ptr::{
nstd_heap_ptr_drop, nstd_heap_ptr_get, nstd_heap_ptr_get_mut, NSTDHeapPtr,
NSTDOptionalHeapPtr,
},
NSTDAny, NSTDAnyMut, NSTDBool,
};
use nstdapi::nstdapi;
use std::sync::{Mutex, MutexGuard, TryLockError};
#[nstdapi]
pub struct NSTDMutex<'a> {
mtx: CBox<Mutex<NSTDHeapPtr<'a>>>,
}
pub type NSTDOptionalMutex<'a> = NSTDOptional<NSTDMutex<'a>>;
#[nstdapi]
pub struct NSTDMutexGuard<'m, 'a> {
guard: CBox<MutexGuard<'m, NSTDHeapPtr<'a>>>,
}
pub type NSTDMutexLockResult<'m, 'a> = NSTDResult<NSTDMutexGuard<'m, 'a>, NSTDMutexGuard<'m, 'a>>;
pub type NSTDOptionalMutexLockResult<'m, 'a> = NSTDOptional<NSTDMutexLockResult<'m, 'a>>;
#[inline]
#[nstdapi]
pub fn nstd_mutex_new(data: NSTDHeapPtr<'_>) -> NSTDOptionalMutex<'_> {
CBox::new(Mutex::new(data)).map_or(NSTDOptional::None, |mtx| {
NSTDOptional::Some(NSTDMutex { mtx })
})
}
#[inline]
#[nstdapi]
pub fn nstd_mutex_is_poisoned(mutex: &NSTDMutex<'_>) -> NSTDBool {
mutex.mtx.is_poisoned()
}
#[nstdapi]
pub fn nstd_mutex_lock<'m, 'a>(mutex: &'m NSTDMutex<'a>) -> NSTDOptionalMutexLockResult<'m, 'a> {
match mutex.mtx.lock() {
Ok(guard) => CBox::new(guard).map_or(NSTDOptional::None, |guard| {
NSTDOptional::Some(NSTDResult::Ok(NSTDMutexGuard { guard }))
}),
Err(err) => CBox::new(err.into_inner()).map_or(NSTDOptional::None, |guard| {
NSTDOptional::Some(NSTDResult::Err(NSTDMutexGuard { guard }))
}),
}
}
#[nstdapi]
pub fn nstd_mutex_try_lock<'m, 'a>(
mutex: &'m NSTDMutex<'a>,
) -> NSTDOptionalMutexLockResult<'m, 'a> {
match mutex.mtx.try_lock() {
Ok(guard) => CBox::new(guard).map_or(NSTDOptional::None, |guard| {
NSTDOptional::Some(NSTDResult::Ok(NSTDMutexGuard { guard }))
}),
Err(err) => match err {
TryLockError::WouldBlock => NSTDOptional::None,
TryLockError::Poisoned(err) => CBox::new(err.into_inner())
.map_or(NSTDOptional::None, |guard| {
NSTDOptional::Some(NSTDResult::Err(NSTDMutexGuard { guard }))
}),
},
}
}
#[inline]
#[nstdapi]
pub fn nstd_mutex_get(guard: &NSTDMutexGuard<'_, '_>) -> NSTDAny {
nstd_heap_ptr_get(&guard.guard)
}
#[inline]
#[nstdapi]
pub fn nstd_mutex_get_mut(guard: &mut NSTDMutexGuard<'_, '_>) -> NSTDAnyMut {
nstd_heap_ptr_get_mut(&mut guard.guard)
}
#[inline]
#[nstdapi]
pub fn nstd_mutex_into_inner(mutex: NSTDMutex<'_>) -> NSTDOptionalHeapPtr<'_> {
mutex
.mtx
.into_inner()
.into_inner()
.map_or(NSTDOptional::None, NSTDOptional::Some)
}
#[inline]
#[nstdapi]
#[allow(
unused_variables,
clippy::missing_const_for_fn,
clippy::needless_pass_by_value
)]
pub fn nstd_mutex_unlock(guard: NSTDMutexGuard<'_, '_>) {}
#[inline]
#[nstdapi]
#[allow(
unused_variables,
clippy::missing_const_for_fn,
clippy::needless_pass_by_value
)]
pub fn nstd_mutex_free(mutex: NSTDMutex<'_>) {}
#[inline]
#[nstdapi]
pub unsafe fn nstd_mutex_drop(mutex: NSTDMutex<'_>, callback: unsafe extern "C" fn(NSTDAnyMut)) {
if let Ok(data) = mutex.mtx.into_inner().into_inner() {
nstd_heap_ptr_drop(data, callback);
}
}