1use core::ops::DerefMut;
2#[cfg(all(feature = "sync", not(feature = "async"), feature = "std"))]
3pub(crate) use std::sync::Mutex;
4
5#[cfg(all(feature = "sync", feature = "async", feature = "smol"))]
6pub(crate) use smol::lock::Mutex;
7#[cfg(all(feature = "sync", not(feature = "std")))]
8pub(crate) use spin::Mutex;
9#[cfg(all(feature = "sync", feature = "async", feature = "tokio"))]
10pub(crate) use tokio::sync::Mutex;
11
12#[cfg(feature = "sync")]
13pub struct Shared<T>(alloc::sync::Arc<Mutex<T>>);
14#[cfg(not(feature = "sync"))]
15pub struct Shared<T>(alloc::rc::Rc<core::cell::RefCell<T>>);
16
17impl<T> Clone for Shared<T> {
18 fn clone(&self) -> Self {
19 Self(self.0.clone())
20 }
21}
22
23impl<T> Shared<T> {
24 pub fn new(value: T) -> Self {
25 match () {
26 #[cfg(feature = "sync")]
27 () => Self(alloc::sync::Arc::new(Mutex::new(value))),
28 #[cfg(not(feature = "sync"))]
29 () => Self(alloc::rc::Rc::new(core::cell::RefCell::new(value))),
30 }
31 }
32}
33
34#[cfg_attr(not(feature = "async"), maybe_async::must_be_sync)]
35impl<T> Shared<T> {
36 pub async fn acquire(&self) -> impl DerefMut<Target = T> {
37 match () {
38 #[cfg(all(feature = "sync", feature = "std", feature = "async"))]
39 () => self.0.lock().await,
40 #[cfg(all(feature = "sync", feature = "std", not(feature = "async")))]
41 () => self.0.lock().unwrap(),
42 #[cfg(all(feature = "sync", not(feature = "std")))]
43 () => self.0.lock(),
44 #[cfg(not(feature = "sync"))]
45 () => self.0.borrow_mut(),
46 }
47 }
48
49 pub async fn try_unwrap(self) -> Result<T, Self> {
50 match () {
51 #[cfg(all(feature = "sync", feature = "async"))]
52 () => alloc::sync::Arc::try_unwrap(self.0).map(|mutex| mutex.into_inner()),
53 #[cfg(all(feature = "sync", feature = "std", not(feature = "async")))]
54 () => alloc::sync::Arc::try_unwrap(self.0).map(|mutex| mutex.into_inner().unwrap()),
55 #[cfg(all(feature = "sync", not(feature = "std"), not(feature = "async")))]
56 () => alloc::sync::Arc::try_unwrap(self.0).map(|mutex| mutex.into_inner()),
57 #[cfg(not(feature = "sync"))]
58 () => alloc::rc::Rc::try_unwrap(self.0).map(|cell| cell.into_inner()),
59 }
60 .map_err(|e| Self(e))
61 }
62}