/rust/registry/src/index.crates.io-1949cf8c6b5b557f/sync_wrapper-1.0.2/src/lib.rs
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2020 Actyx AG |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | //! A mutual exclusion primitive that relies on static type information only |
17 | | //! |
18 | | //! This library is inspired by [this discussion](https://internals.rust-lang.org/t/what-shall-sync-mean-across-an-await/12020/2). |
19 | | #![doc(html_logo_url = "https://developer.actyx.com/img/logo.svg")] |
20 | | #![doc(html_favicon_url = "https://developer.actyx.com/img/favicon.ico")] |
21 | | #![no_std] |
22 | | |
23 | | use core::{ |
24 | | fmt::{self, Debug, Formatter}, |
25 | | pin::Pin, |
26 | | future::Future, |
27 | | task::{Context, Poll}, |
28 | | }; |
29 | | |
30 | | /// A mutual exclusion primitive that relies on static type information only |
31 | | /// |
32 | | /// In some cases synchronization can be proven statically: whenever you hold an exclusive `&mut` |
33 | | /// reference, the Rust type system ensures that no other part of the program can hold another |
34 | | /// reference to the data. Therefore it is safe to access it even if the current thread obtained |
35 | | /// this reference via a channel. Whenever this is the case, the overhead of allocating and locking |
36 | | /// a [`Mutex`] can be avoided by using this static version. |
37 | | /// |
38 | | /// One example where this is often applicable is [`Future`], which requires an exclusive reference |
39 | | /// for its [`poll`] method: While a given `Future` implementation may not be safe to access by |
40 | | /// multiple threads concurrently, the executor can only run the `Future` on one thread at any |
41 | | /// given time, making it [`Sync`] in practice as long as the implementation is `Send`. You can |
42 | | /// therefore use the static mutex to prove that your data structure is `Sync` even though it |
43 | | /// contains such a `Future`. |
44 | | /// |
45 | | /// # Example |
46 | | /// |
47 | | /// ``` |
48 | | /// use sync_wrapper::SyncWrapper; |
49 | | /// use std::future::Future; |
50 | | /// |
51 | | /// struct MyThing { |
52 | | /// future: SyncWrapper<Box<dyn Future<Output = String> + Send>>, |
53 | | /// } |
54 | | /// |
55 | | /// impl MyThing { |
56 | | /// // all accesses to `self.future` now require an exclusive reference or ownership |
57 | | /// } |
58 | | /// |
59 | | /// fn assert_sync<T: Sync>() {} |
60 | | /// |
61 | | /// assert_sync::<MyThing>(); |
62 | | /// ``` |
63 | | /// |
64 | | /// [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html |
65 | | /// [`Future`]: https://doc.rust-lang.org/std/future/trait.Future.html |
66 | | /// [`poll`]: https://doc.rust-lang.org/std/future/trait.Future.html#method.poll |
67 | | /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html |
68 | | #[repr(transparent)] |
69 | | pub struct SyncWrapper<T>(T); |
70 | | |
71 | | impl<T> SyncWrapper<T> { |
72 | | /// Creates a new static mutex containing the given value. |
73 | | /// |
74 | | /// # Examples |
75 | | /// |
76 | | /// ``` |
77 | | /// use sync_wrapper::SyncWrapper; |
78 | | /// |
79 | | /// let mutex = SyncWrapper::new(42); |
80 | | /// ``` |
81 | 0 | pub const fn new(value: T) -> Self { |
82 | 0 | Self(value) |
83 | 0 | } Unexecuted instantiation: <sync_wrapper::SyncWrapper<alloc::boxed::Box<dyn tonic::codec::Decoder<Item = ztunnel::xds::types::istio::ca::IstioCertificateResponse, Error = tonic::status::Status> + core::marker::Send>>>::new Unexecuted instantiation: <sync_wrapper::SyncWrapper<alloc::boxed::Box<dyn tonic::codec::Decoder<Item = ztunnel::xds::types::service::discovery::v3::DeltaDiscoveryResponse, Error = tonic::status::Status> + core::marker::Send>>>::new Unexecuted instantiation: <sync_wrapper::SyncWrapper<tonic::body::Body>>::new |
84 | | |
85 | | /// Acquires a reference to the protected value. |
86 | | /// |
87 | | /// This is safe because it requires an exclusive reference to the mutex. Therefore this method |
88 | | /// neither panics nor does it return an error. This is in contrast to [`Mutex::get_mut`] which |
89 | | /// returns an error if another thread panicked while holding the lock. It is not recommended |
90 | | /// to send an exclusive reference to a potentially damaged value to another thread for further |
91 | | /// processing. |
92 | | /// |
93 | | /// [`Mutex::get_mut`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#method.get_mut |
94 | | /// |
95 | | /// # Examples |
96 | | /// |
97 | | /// ``` |
98 | | /// use sync_wrapper::SyncWrapper; |
99 | | /// |
100 | | /// let mut mutex = SyncWrapper::new(42); |
101 | | /// let value = mutex.get_mut(); |
102 | | /// *value = 0; |
103 | | /// assert_eq!(*mutex.get_mut(), 0); |
104 | | /// ``` |
105 | 0 | pub fn get_mut(&mut self) -> &mut T { |
106 | 0 | &mut self.0 |
107 | 0 | } Unexecuted instantiation: <sync_wrapper::SyncWrapper<alloc::boxed::Box<dyn tonic::codec::Decoder<Item = ztunnel::xds::types::istio::ca::IstioCertificateResponse, Error = tonic::status::Status> + core::marker::Send>>>::get_mut Unexecuted instantiation: <sync_wrapper::SyncWrapper<alloc::boxed::Box<dyn tonic::codec::Decoder<Item = ztunnel::xds::types::service::discovery::v3::DeltaDiscoveryResponse, Error = tonic::status::Status> + core::marker::Send>>>::get_mut Unexecuted instantiation: <sync_wrapper::SyncWrapper<tonic::body::Body>>::get_mut |
108 | | |
109 | | /// Acquires a pinned reference to the protected value. |
110 | | /// |
111 | | /// See [`Self::get_mut`] for why this method is safe. |
112 | | /// |
113 | | /// # Examples |
114 | | /// |
115 | | /// ``` |
116 | | /// use std::future::Future; |
117 | | /// use std::pin::Pin; |
118 | | /// use std::task::{Context, Poll}; |
119 | | /// |
120 | | /// use pin_project_lite::pin_project; |
121 | | /// use sync_wrapper::SyncWrapper; |
122 | | /// |
123 | | /// pin_project! { |
124 | | /// struct FutureWrapper<F> { |
125 | | /// #[pin] |
126 | | /// inner: SyncWrapper<F>, |
127 | | /// } |
128 | | /// } |
129 | | /// |
130 | | /// impl<F: Future> Future for FutureWrapper<F> { |
131 | | /// type Output = F::Output; |
132 | | /// |
133 | | /// fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
134 | | /// self.project().inner.get_pin_mut().poll(cx) |
135 | | /// } |
136 | | /// } |
137 | | /// ``` |
138 | | pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { |
139 | | unsafe { Pin::map_unchecked_mut(self, |this| &mut this.0) } |
140 | | } |
141 | | |
142 | | /// Consumes this mutex, returning the underlying data. |
143 | | /// |
144 | | /// This is safe because it requires ownership of the mutex, therefore this method will neither |
145 | | /// panic nor does it return an error. This is in contrast to [`Mutex::into_inner`] which |
146 | | /// returns an error if another thread panicked while holding the lock. It is not recommended |
147 | | /// to send an exclusive reference to a potentially damaged value to another thread for further |
148 | | /// processing. |
149 | | /// |
150 | | /// [`Mutex::into_inner`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#method.into_inner |
151 | | /// |
152 | | /// # Examples |
153 | | /// |
154 | | /// ``` |
155 | | /// use sync_wrapper::SyncWrapper; |
156 | | /// |
157 | | /// let mut mutex = SyncWrapper::new(42); |
158 | | /// assert_eq!(mutex.into_inner(), 42); |
159 | | /// ``` |
160 | | pub fn into_inner(self) -> T { |
161 | | self.0 |
162 | | } |
163 | | } |
164 | | |
165 | | // this is safe because the only operations permitted on this data structure require exclusive |
166 | | // access or ownership |
167 | | unsafe impl<T> Sync for SyncWrapper<T> {} |
168 | | |
169 | | impl<T> Debug for SyncWrapper<T> { |
170 | | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
171 | | f.pad("SyncWrapper") |
172 | | } |
173 | | } |
174 | | |
175 | | impl<T: Default> Default for SyncWrapper<T> { |
176 | | fn default() -> Self { |
177 | | Self::new(T::default()) |
178 | | } |
179 | | } |
180 | | |
181 | | impl<T> From<T> for SyncWrapper<T> { |
182 | | fn from(value: T) -> Self { |
183 | | Self::new(value) |
184 | | } |
185 | | } |
186 | | |
187 | | /// `Future` which is `Sync`. |
188 | | /// |
189 | | /// # Examples |
190 | | /// |
191 | | /// ``` |
192 | | /// use sync_wrapper::{SyncWrapper, SyncFuture}; |
193 | | /// |
194 | | /// let fut = async { 1 }; |
195 | | /// let fut = SyncFuture::new(fut); |
196 | | /// ``` |
197 | | pub struct SyncFuture<F> { |
198 | | inner: SyncWrapper<F> |
199 | | } |
200 | | impl <F: Future> SyncFuture<F> { |
201 | | pub fn new(inner: F) -> Self { |
202 | | Self { inner: SyncWrapper::new(inner) } |
203 | | } |
204 | | pub fn into_inner(self) -> F { |
205 | | self.inner.into_inner() |
206 | | } |
207 | | } |
208 | | impl <F: Future> Future for SyncFuture<F> { |
209 | | type Output = F::Output; |
210 | | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
211 | | let inner = unsafe { self.map_unchecked_mut(|x| x.inner.get_mut()) }; |
212 | | inner.poll(cx) |
213 | | } |
214 | | } |
215 | | impl<T> Debug for SyncFuture<T> { |
216 | | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
217 | | f.pad("SyncFuture") |
218 | | } |
219 | | } |
220 | | |
221 | | /// `Stream` which is `Sync`. |
222 | | /// |
223 | | /// # Examples |
224 | | /// |
225 | | /// ``` |
226 | | /// use sync_wrapper::SyncStream; |
227 | | /// use futures::stream; |
228 | | /// |
229 | | /// let st = stream::iter(vec![1]); |
230 | | /// let st = SyncStream::new(st); |
231 | | /// ``` |
232 | | #[cfg(feature = "futures")] |
233 | | pub struct SyncStream<S> { |
234 | | inner: SyncWrapper<S> |
235 | | } |
236 | | #[cfg(feature = "futures")] |
237 | | impl <S: futures_core::Stream> SyncStream<S> { |
238 | | pub fn new(inner: S) -> Self { |
239 | | Self { inner: SyncWrapper::new(inner) } |
240 | | } |
241 | | pub fn into_inner(self) -> S { |
242 | | self.inner.into_inner() |
243 | | } |
244 | | } |
245 | | #[cfg(feature = "futures")] |
246 | | impl <S: futures_core::Stream> futures_core::Stream for SyncStream<S> { |
247 | | type Item = S::Item; |
248 | | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { |
249 | | let inner = unsafe { self.map_unchecked_mut(|x| x.inner.get_mut()) }; |
250 | | inner.poll_next(cx) |
251 | | } |
252 | | } |
253 | | #[cfg(feature = "futures")] |
254 | | impl<T> Debug for SyncStream<T> { |
255 | | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
256 | | f.pad("SyncStream") |
257 | | } |
258 | | } |