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> {}