firewheel_core/
sync_wrapper.rs

1/// A wrapper around a non-`Sync` type to make it `Sync`.
2///
3/// The mechanism is very simple. [`SyncWrapper`] prevents
4/// shared borrowing of the inner type. The only way to get
5/// to the inner data is through `take` or `get_mut`. Both methods
6/// can only be called with a mutable reference to [`SyncWrapper`],
7/// so it's not possible that the inner value can be observed
8/// simultaneously in multiple threads.
9#[derive(Debug)]
10pub struct SyncWrapper<T>(Option<T>);
11
12impl<T> SyncWrapper<T> {
13    /// Construct a new [`SyncWrapper`].
14    pub fn new(value: T) -> Self {
15        Self(Some(value))
16    }
17
18    /// Move out the inner value.
19    ///
20    /// If this has already been called on this thread or elsewhere,
21    /// this will return `None`.
22    pub fn take(&mut self) -> Option<T> {
23        self.0.take()
24    }
25
26    /// Obtain a mutable reference to the inner value.
27    ///
28    /// If `take` has been called previously, this returns `None`.
29    pub fn get_mut(&mut self) -> Option<&mut T> {
30        self.0.as_mut()
31    }
32}
33
34/// # Safety
35///
36/// [`SyncWrapper`] prevents
37/// shared borrowing of the inner type. The only way to get
38/// to the inner data is through `take` or `get_mut`. Both methods
39/// can only be called with a mutable reference to [`SyncWrapper`],
40/// so it's not possible that the inner value can be observed
41/// simultaneously in multiple threads.
42///
43/// Therefore, this implementation is safe.
44///
45/// For further reference, see the [standard library's
46/// implementation of `Sync` on `std::sync::Mutex`](https://doc.rust-lang.org/src/std/sync/poison/mutex.rs.html#189),
47/// as well as the [`get_mut` method](https://doc.rust-lang.org/src/std/sync/poison/mutex.rs.html#557-581).
48unsafe impl<T: Send> Sync for SyncWrapper<T> {}