use std::fmt::{Debug, Display, Formatter};
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use futures::lock::{Mutex, MutexGuard};
use serde_derive::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StillSharedError(usize);
impl Display for StillSharedError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "resource is still shared by {} instances", self.0)
}
}
impl std::error::Error for StillSharedError {}
#[derive(Debug)]
pub struct ResourceLock<'r, R> {
inner: MutexGuard<'r, R>,
}
impl<'r, R> Deref for ResourceLock<'r, R> {
type Target = R;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<'r, R> DerefMut for ResourceLock<'r, R> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
#[derive(Debug, Default)]
pub struct SharedResource<R> {
inner: Arc<Mutex<R>>,
}
impl<R> Clone for SharedResource<R> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<R> SharedResource<R> {
pub fn new(inner: R) -> Self {
Self {
inner: Arc::new(Mutex::new(inner)),
}
}
pub async fn borrow(&self) -> ResourceLock<'_, R> {
let lock = self.inner.lock().await;
ResourceLock { inner: lock }
}
pub fn into_original(self) -> Result<R, StillSharedError> {
let mutex = Arc::try_unwrap(self.inner).map_err(|arc| {
let count = Arc::strong_count(&arc);
StillSharedError(count)
})?;
Ok(mutex.into_inner())
}
}