use super::{lock, CoordinateError, Subject};
use either::{Either, Left, Right};
pub trait FacetFree {
type FacetFree<'a>
where
Self: 'a;
fn facet_free(&self) -> Self::FacetFree<'_>;
}
pub trait FacetShared {
type FacetShared<'a>
where
Self: 'a;
fn facet_shared(&self) -> Self::FacetShared<'_>;
}
pub trait FacetExclusive {
type FacetExclusive<'a>
where
Self: 'a;
fn facet_exclusive(&self) -> Self::FacetExclusive<'_>;
}
pub struct ResourceFree<S: Subject> {
lock: lock::UnlockedFile,
subject: S,
}
impl<S: Subject> ResourceFree<S> {
pub fn new(lock: lock::UnlockedFile, inner: S) -> Self {
Self { lock, subject: inner }
}
pub fn try_shared(self) -> Result<Either<Self, ResourceShared<S>>, CoordinateError<S::Error>> {
Ok(match self.lock.try_lock_shared()? {
Left(lock) => Left(Self { subject: self.subject, lock }),
Right(lock) => Right(ResourceShared { subject: self.subject, lock }),
})
}
pub fn shared(self) -> Result<ResourceShared<S>, CoordinateError<S::Error>> {
let lock = self.lock.lock_shared()?;
Ok(ResourceShared { subject: self.subject, lock })
}
pub fn try_exclusive(
self,
) -> Result<Either<Self, ResourceExclusive<S>>, CoordinateError<S::Error>> {
Ok(match self.lock.try_lock_exclusive()? {
Left(lock) => Left(Self { subject: self.subject, lock }),
Right(lock) => Right(ResourceExclusive { subject: self.subject, lock }),
})
}
pub fn exclusive(self) -> Result<ResourceExclusive<S>, CoordinateError<S::Error>> {
let lock = self.lock.lock_exclusive()?;
Ok(ResourceExclusive { subject: self.subject, lock })
}
pub fn into_parts(self) -> (lock::UnlockedFile, S) {
(self.lock, self.subject)
}
}
impl<S: Subject + FacetFree> ResourceFree<S> {
pub fn facet(&self) -> S::FacetFree<'_> {
self.subject.facet_free()
}
}
pub struct ResourceShared<S: Subject> {
lock: lock::LockedFileShared,
subject: S,
}
impl<S: Subject> ResourceShared<S> {
pub fn new(lock: lock::LockedFileShared, inner: S) -> Self {
Self { lock, subject: inner }
}
pub fn try_exclusive(
self,
) -> Result<Either<Self, ResourceExclusive<S>>, CoordinateError<S::Error>> {
Ok(match self.lock.try_lock_exclusive()? {
Left(lock) => Left(Self { subject: self.subject, lock }),
Right(lock) => Right(ResourceExclusive { subject: self.subject, lock }),
})
}
pub fn exclusive(self) -> Result<ResourceExclusive<S>, CoordinateError<S::Error>> {
let lock = self.lock.lock_exclusive()?;
Ok(ResourceExclusive { subject: self.subject, lock })
}
pub fn try_release(self) -> Result<Either<Self, ResourceFree<S>>, CoordinateError<S::Error>> {
Ok(match self.lock.try_unlock()? {
Left(lock) => Left(Self { subject: self.subject, lock }),
Right(lock) => Right(ResourceFree { subject: self.subject, lock }),
})
}
pub fn release(self) -> Result<ResourceFree<S>, CoordinateError<S::Error>> {
let lock = self.lock.unlock()?;
Ok(ResourceFree { subject: self.subject, lock })
}
}
impl<S: Subject + FacetShared> ResourceShared<S> {
pub fn facet(&self) -> S::FacetShared<'_> {
self.subject.facet_shared()
}
}
pub struct ResourceExclusive<S: Subject> {
lock: lock::LockedFileExclusive,
subject: S,
}
impl<S: Subject> ResourceExclusive<S> {
pub fn new(lock: lock::LockedFileExclusive, inner: S) -> Self {
Self { lock, subject: inner }
}
pub fn try_shared(self) -> Result<Either<Self, ResourceShared<S>>, CoordinateError<S::Error>> {
Ok(match self.lock.try_lock_shared()? {
Left(lock) => Left(Self { subject: self.subject, lock }),
Right(lock) => Right(ResourceShared { subject: self.subject, lock }),
})
}
pub fn shared(self) -> Result<ResourceShared<S>, CoordinateError<S::Error>> {
let lock = self.lock.lock_shared()?;
Ok(ResourceShared { subject: self.subject, lock })
}
pub fn try_release(self) -> Result<Either<Self, ResourceFree<S>>, CoordinateError<S::Error>> {
Ok(match self.lock.try_unlock()? {
Left(lock) => Left(Self { subject: self.subject, lock }),
Right(lock) => Right(ResourceFree { subject: self.subject, lock }),
})
}
pub fn release(self) -> Result<ResourceFree<S>, CoordinateError<S::Error>> {
let lock = self.lock.unlock()?;
Ok(ResourceFree { subject: self.subject, lock })
}
}
impl<S: Subject + FacetExclusive> ResourceExclusive<S> {
pub fn facet(&self) -> S::FacetExclusive<'_> {
self.subject.facet_exclusive()
}
}