use core::fmt;
use crate::maybe_sync::{self, MaRc, MaWeak};
use crate::{Listener, Store};
#[derive(Default)]
pub struct StoreLock<T: ?Sized>(MaRc<maybe_sync::Mutex<T>>);
pub struct StoreLockListener<T: ?Sized>(MaWeak<maybe_sync::Mutex<T>>);
impl<T: ?Sized + fmt::Debug> fmt::Debug for StoreLock<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self(mutex) = self;
f.debug_tuple("StoreLock").field(&&*mutex.lock()).finish()
}
}
impl<T: ?Sized> fmt::Debug for StoreLockListener<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("StoreLockListener")
.field("type", &crate::util::Unquote::type_name::<T>())
.field("alive", &self.alive())
.finish()
}
}
impl<T: ?Sized> fmt::Pointer for StoreLock<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
MaRc::as_ptr(&self.0).fmt(f)
}
}
impl<T: ?Sized> fmt::Pointer for StoreLockListener<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.as_ptr().fmt(f)
}
}
impl<T> StoreLock<T> {
pub fn new(initial_state: T) -> Self {
Self(MaRc::new(maybe_sync::Mutex::new(initial_state)))
}
}
impl<T: ?Sized> StoreLock<T> {
#[must_use]
pub fn listener(&self) -> StoreLockListener<T> {
StoreLockListener(MaRc::downgrade(&self.0))
}
#[must_use]
pub fn lock(&self) -> impl core::ops::DerefMut<Target = T> + use<'_, T> {
self.0.lock()
}
#[must_use]
pub fn take(&self) -> T
where
T: Sized + Default,
{
let replacement: T = T::default();
let state: &mut T = &mut *self.0.lock();
core::mem::replace(state, replacement)
}
pub fn receive<M>(&self, messages: &[M])
where
T: Store<M>,
{
receive_bare_mutex(&self.0, messages);
}
}
impl<T: ?Sized> StoreLockListener<T> {
pub(crate) fn alive(&self) -> bool {
self.0.strong_count() > 0
}
}
impl<M, T: ?Sized + Store<M> + Send> Listener<M> for StoreLockListener<T> {
fn receive(&self, messages: &[M]) -> bool {
let Some(strong) = self.0.upgrade() else {
return false;
};
if messages.is_empty() {
return true;
}
receive_bare_mutex(&*strong, messages)
}
}
impl<T: ?Sized + Store<M> + Send, M> crate::FromListener<StoreLockListener<T>, M>
for StoreLockListener<T>
{
fn from_listener(listener: StoreLockListener<T>) -> Self {
listener
}
}
fn receive_bare_mutex<M, T: ?Sized + Store<M>>(
mutex: &maybe_sync::Mutex<T>,
messages: &[M],
) -> bool {
mutex.lock().receive(messages);
true
}
impl<T: ?Sized> Clone for StoreLockListener<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}