fuser_async/
rwlockoption.rs1use std::sync::Arc;
4
5#[derive(Clone)]
6pub struct RwLockOption<T>(Arc<tokio::sync::RwLock<Option<T>>>);
7pub type RwLockOptionGuard<T> = tokio::sync::OwnedRwLockReadGuard<Option<T>, T>;
8pub type RwLockOptionWriteGuard<T> = tokio::sync::OwnedRwLockMappedWriteGuard<Option<T>, T>;
9impl<T> RwLockOption<T> {
10 pub async fn get_or_try_init<E, F: std::future::Future<Output = Result<T, E>>>(
11 &self,
12 f: impl FnOnce() -> F,
13 ) -> Result<RwLockOptionGuard<T>, E> {
14 let s = self.0.clone().read_owned().await;
15 let s = if s.is_none() {
16 drop(s);
17 let mut s = self.0.clone().write_owned().await;
18 if s.is_none() {
19 *s = Some(f().await?);
20 }
21 drop(s);
28 self.0.clone().read_owned().await
29 } else {
30 s
31 };
32 Ok(tokio::sync::OwnedRwLockReadGuard::map(s, |x| {
33 x.as_ref().unwrap()
34 }))
35 }
36 pub async fn get_mut_or_try_init<E, F: std::future::Future<Output = Result<T, E>>>(
37 &self,
38 f: impl FnOnce() -> F,
39 ) -> Result<RwLockOptionWriteGuard<T>, E> {
40 let mut s = self.0.clone().write_owned().await;
41 if s.is_none() {
42 *s = Some(f().await?);
43 }
44 Ok(tokio::sync::OwnedRwLockWriteGuard::map(s, |s| match s {
45 Some(s) => s,
46 None => unreachable!(),
47 }))
48 }
49 pub fn is_some(&self) -> Option<bool> {
50 self.0.try_read().ok().map(|s| s.is_some())
51 }
52 pub fn try_read(&self) -> Option<RwLockOptionGuard<T>> {
53 let data = self.0.clone().try_read_owned().ok()?;
54 if data.is_none() {
55 return None;
56 }
57 Some(tokio::sync::OwnedRwLockReadGuard::map(data, |x| {
58 x.as_ref().unwrap()
59 }))
60 }
61 pub async fn clear(&self) -> anyhow::Result<()> {
62 let mut s = self.0.try_write()?;
63 s.take();
64 Ok(())
65 }
66 pub fn new() -> Self {
67 Self(Arc::new(tokio::sync::RwLock::new(None)))
68 }
69}
70impl<T> Default for RwLockOption<T> {
71 fn default() -> Self {
72 Self::new()
73 }
74}