use prelude::v1::*;
use base::*;
use units::*;
use shim::*;
unsafe impl<T: Sync + Send> Send for Mutex<T> {}
unsafe impl<T: Sync + Send> Sync for Mutex<T> {}
pub struct Mutex<T: ?Sized> {
mutex: FreeRtosSemaphoreHandle,
recursive: bool,
data: UnsafeCell<T>,
}
impl<T: ?Sized> fmt::Debug for Mutex<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"Mutex address: {:?}, recursive: {:?}",
self.mutex,
self.recursive)
}
}
impl<T> Mutex<T> {
fn new_mutex(t: T, recursive: bool) -> Result<Mutex<T>, FreeRtosError> {
unsafe {
let m = if recursive {
freertos_rs_create_recursive_mutex()
} else {
freertos_rs_create_mutex()
};
if m == 0 as *const _ {
return Err(FreeRtosError::OutOfMemory);
}
let mutex = Mutex {
mutex: m,
recursive: recursive,
data: UnsafeCell::new(t),
};
Ok(mutex)
}
}
pub fn new(t: T) -> Result<Mutex<T>, FreeRtosError> {
Self::new_mutex(t, false)
}
pub fn new_recursive(t: T) -> Result<Mutex<T>, FreeRtosError> {
Self::new_mutex(t, true)
}
pub fn lock(&self, max_wait: Duration) -> Result<MutexGuard<T>, FreeRtosError> {
unsafe {
let res = if self.recursive {
freertos_rs_take_recursive_mutex(self.mutex, max_wait.to_ticks())
} else {
freertos_rs_take_mutex(self.mutex, max_wait.to_ticks())
};
if res != 0 {
return Err(FreeRtosError::Timeout);
}
Ok(MutexGuard {
__mutex: self.mutex,
__recursive: self.recursive,
__data: &self.data,
})
}
}
pub fn into_inner(self) -> T {
unsafe {
let (mutex, data) = {
let Mutex { ref mutex, recursive: _, ref data } = self;
(ptr::read(mutex), ptr::read(data))
};
mem::forget(self);
freertos_rs_delete_semaphore(mutex);
data.into_inner()
}
}
}
impl<T: ?Sized> Drop for Mutex<T> {
fn drop(&mut self) {
unsafe {
freertos_rs_delete_semaphore(self.mutex);
}
}
}
pub struct MutexGuard<'a, T: ?Sized + 'a> {
__mutex: FreeRtosSemaphoreHandle,
__recursive: bool,
__data: &'a UnsafeCell<T>,
}
impl<'mutex, T: ?Sized> Deref for MutexGuard<'mutex, T> {
type Target = T;
fn deref<'a>(&'a self) -> &'a T {
unsafe { &*self.__data.get() }
}
}
impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
unsafe { &mut *self.__data.get() }
}
}
impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
fn drop(&mut self) {
unsafe {
if self.__recursive {
freertos_rs_give_recursive_mutex(self.__mutex);
} else {
freertos_rs_give_mutex(self.__mutex);
}
}
}
}