pikadick_util/
async_lock_file.rs1use anyhow::Context;
2use fslock::{
3 IntoOsString,
4 LockFile,
5 ToOsStr,
6};
7use std::sync::Arc;
8
9#[derive(Debug, Clone)]
13pub struct AsyncLockFile {
14 file: Arc<tokio::sync::Mutex<LockFile>>,
15}
16
17impl AsyncLockFile {
18 pub async fn open<P>(path: P) -> anyhow::Result<Self>
20 where
21 P: IntoOsString,
22 {
23 let path = path.into_os_string()?;
24 tokio::task::spawn_blocking(move || Self::blocking_open(&path))
25 .await
26 .context("failed to join task")?
27 }
28
29 pub fn blocking_open<P>(path: &P) -> anyhow::Result<Self>
31 where
32 P: ToOsStr + ?Sized,
33 {
34 let file = LockFile::open(path)?;
35 Ok(Self {
36 file: Arc::new(tokio::sync::Mutex::new(file)),
37 })
38 }
39
40 pub async fn lock(&self) -> anyhow::Result<()> {
42 let mut file = self.file.clone().lock_owned().await;
43 Ok(tokio::task::spawn_blocking(move || file.lock())
44 .await
45 .context("failed to join task")??)
46 }
47
48 pub async fn lock_with_pid(&self) -> anyhow::Result<()> {
50 let mut file = self.file.clone().lock_owned().await;
51 Ok(tokio::task::spawn_blocking(move || file.lock_with_pid())
52 .await
53 .context("failed to join task")??)
54 }
55
56 pub async fn try_lock(&self) -> anyhow::Result<bool> {
58 let mut file = self.file.clone().lock_owned().await;
59 Ok(tokio::task::spawn_blocking(move || file.try_lock())
60 .await
61 .context("failed to join task")??)
62 }
63
64 pub async fn try_lock_with_pid(&self) -> anyhow::Result<bool> {
66 let mut file = self.file.clone().lock_owned().await;
67 Ok(
68 tokio::task::spawn_blocking(move || file.try_lock_with_pid())
69 .await
70 .context("failed to join task")??,
71 )
72 }
73
74 pub fn try_lock_with_pid_blocking(&self) -> anyhow::Result<bool> {
76 Ok(self.file.blocking_lock().try_lock_with_pid()?)
77 }
78
79 pub async fn owns_lock(&self) -> anyhow::Result<bool> {
81 let file = self.file.clone().lock_owned().await;
82 tokio::task::spawn_blocking(move || file.owns_lock())
83 .await
84 .context("failed to join task")
85 }
86
87 pub async fn unlock(&self) -> anyhow::Result<()> {
89 let mut file = self.file.clone().lock_owned().await;
90 Ok(tokio::task::spawn_blocking(move || file.unlock())
91 .await
92 .context("failed to join task")??)
93 }
94
95 pub fn blocking_unlock(&self) -> anyhow::Result<()> {
97 Ok(self.file.blocking_lock().unlock()?)
98 }
99}