async_drop_guard/
async_drop_arc.rs

1use async_trait::async_trait;
2use std::borrow::Borrow;
3use std::fmt::Debug;
4use std::ops::Deref;
5use std::sync::Arc;
6
7use super::{AsyncDrop, AsyncDropGuard};
8
9#[derive(Debug)]
10// TODO Why do we need Send + Sync? std::sync::Arc doesn't seem to need it
11pub struct AsyncDropArc<T: AsyncDrop + Debug + Sync + Send> {
12    // Always Some except during destruction
13    v: Option<Arc<AsyncDropGuard<T>>>,
14}
15
16impl<T: AsyncDrop + Debug + Sync + Send> AsyncDropArc<T> {
17    pub fn new(v: AsyncDropGuard<T>) -> AsyncDropGuard<Self> {
18        AsyncDropGuard::new(Self {
19            v: Some(Arc::new(v)),
20        })
21    }
22
23    pub fn clone(this: &AsyncDropGuard<Self>) -> AsyncDropGuard<Self> {
24        AsyncDropGuard::new(Self {
25            v: this.v.as_ref().map(|v| Arc::clone(v)),
26        })
27    }
28}
29
30#[async_trait]
31impl<T: AsyncDrop + Debug + Sync + Send> AsyncDrop for AsyncDropArc<T> {
32    type Error = T::Error;
33
34    async fn async_drop_impl(&mut self) -> Result<(), Self::Error> {
35        let v = self.v.take().expect("Already destructed");
36        if let Ok(mut v) = Arc::try_unwrap(v) {
37            v.async_drop().await?;
38        }
39        Ok(())
40    }
41}
42
43impl<T: AsyncDrop + Debug + Sync + Send> Deref for AsyncDropArc<T> {
44    type Target = T;
45    fn deref(&self) -> &T {
46        self.v.as_ref().expect("Already destructed").deref()
47    }
48}
49
50impl<T: AsyncDrop + Debug + Sync + Send> Borrow<T> for AsyncDropArc<T> {
51    fn borrow(&self) -> &T {
52        Borrow::<AsyncDropGuard<T>>::borrow(Borrow::<Arc<AsyncDropGuard<T>>>::borrow(
53            self.v.as_ref().expect("Already destructed"),
54        ))
55        .borrow()
56    }
57}
58
59// TODO Tests