micro_tower/util/
borrow.rs

1use std::ops::{Deref, DerefMut};
2use std::sync::{Arc, Mutex};
3
4/// Implements a thread safe data structure which can be used to temporary borrow an inner value.
5pub struct Cell<T> {
6    inner: Arc<Mutex<Option<T>>>,
7}
8
9/// Used to wrap a borrowed value. Will return the borrowed value then dropped.
10pub struct Borrowed<T> {
11    ret: Arc<Mutex<Option<T>>>,
12    value: Option<T>,
13}
14
15impl<T> Cell<T> {
16    pub fn new(value: T) -> Self {
17        Self {
18            inner: Arc::new(Mutex::new(Some(value))),
19        }
20    }
21
22    /// Returns `true` if the inner value is available to borrow. Returns `false` if value already
23    /// borrowed.
24    ///
25    /// # Panics
26    ///
27    /// Will panic if failed to lock the inner variable.
28    #[must_use]
29    pub fn is_available(&self) -> bool {
30        self.inner.lock().unwrap().is_some()
31    }
32
33    /// Tries to borrow the inner value. Will return `None` if inner value couldn't be borrowed.
34    ///
35    /// # Panics
36    ///
37    /// Will panic if failed to lock the inner variable.
38    #[must_use]
39    pub fn try_borrow(&self) -> Option<Borrowed<T>> {
40        self.inner.lock().unwrap().take().map(|value| Borrowed {
41            ret: self.inner.clone(),
42            value: Some(value),
43        })
44    }
45}
46
47impl<T: Clone> Cell<T> {
48    /// Tries to clone inner cell. Will return `None` if inner value is borrowed.
49    #[must_use]
50    pub fn fork(&self) -> Option<Cell<T>> {
51        if let Some(inner) = self.try_borrow() {
52            return Some(Cell::new(inner.clone()));
53        }
54        None
55    }
56}
57
58impl<T> Drop for Borrowed<T> {
59    fn drop(&mut self) {
60        let value = self.value.take().expect("can only be dropped once");
61        self.ret.lock().unwrap().replace(value);
62    }
63}
64
65impl<T> Deref for Borrowed<T> {
66    type Target = T;
67
68    fn deref(&self) -> &Self::Target {
69        self.value.as_ref().expect("already dropped")
70    }
71}
72
73impl<T> DerefMut for Borrowed<T> {
74    fn deref_mut(&mut self) -> &mut Self::Target {
75        self.value.as_mut().expect("already dropped")
76    }
77}