• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use super::{Semaphore, SemaphorePermit, TryAcquireError};
2 use crate::loom::cell::UnsafeCell;
3 use std::error::Error;
4 use std::fmt;
5 use std::future::Future;
6 use std::mem::MaybeUninit;
7 use std::ops::Drop;
8 use std::ptr;
9 use std::sync::atomic::{AtomicBool, Ordering};
10 
11 // This file contains an implementation of an OnceCell. The principle
12 // behind the safety the of the cell is that any thread with an `&OnceCell` may
13 // access the `value` field according the following rules:
14 //
15 //  1. When `value_set` is false, the `value` field may be modified by the
16 //     thread holding the permit on the semaphore.
17 //  2. When `value_set` is true, the `value` field may be accessed immutably by
18 //     any thread.
19 //
20 // It is an invariant that if the semaphore is closed, then `value_set` is true.
21 // The reverse does not necessarily hold — but if not, the semaphore may not
22 // have any available permits.
23 //
24 // A thread with a `&mut OnceCell` may modify the value in any way it wants as
25 // long as the invariants are upheld.
26 
27 /// A thread-safe cell that can be written to only once.
28 ///
29 /// A `OnceCell` is typically used for global variables that need to be
30 /// initialized once on first use, but need no further changes. The `OnceCell`
31 /// in Tokio allows the initialization procedure to be asynchronous.
32 ///
33 /// # Examples
34 ///
35 /// ```
36 /// use tokio::sync::OnceCell;
37 ///
38 /// async fn some_computation() -> u32 {
39 ///     1 + 1
40 /// }
41 ///
42 /// static ONCE: OnceCell<u32> = OnceCell::const_new();
43 ///
44 /// #[tokio::main]
45 /// async fn main() {
46 ///     let result = ONCE.get_or_init(some_computation).await;
47 ///     assert_eq!(*result, 2);
48 /// }
49 /// ```
50 ///
51 /// It is often useful to write a wrapper method for accessing the value.
52 ///
53 /// ```
54 /// use tokio::sync::OnceCell;
55 ///
56 /// static ONCE: OnceCell<u32> = OnceCell::const_new();
57 ///
58 /// async fn get_global_integer() -> &'static u32 {
59 ///     ONCE.get_or_init(|| async {
60 ///         1 + 1
61 ///     }).await
62 /// }
63 ///
64 /// #[tokio::main]
65 /// async fn main() {
66 ///     let result = get_global_integer().await;
67 ///     assert_eq!(*result, 2);
68 /// }
69 /// ```
70 pub struct OnceCell<T> {
71     value_set: AtomicBool,
72     value: UnsafeCell<MaybeUninit<T>>,
73     semaphore: Semaphore,
74 }
75 
76 impl<T> Default for OnceCell<T> {
default() -> OnceCell<T>77     fn default() -> OnceCell<T> {
78         OnceCell::new()
79     }
80 }
81 
82 impl<T: fmt::Debug> fmt::Debug for OnceCell<T> {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result83     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
84         fmt.debug_struct("OnceCell")
85             .field("value", &self.get())
86             .finish()
87     }
88 }
89 
90 impl<T: Clone> Clone for OnceCell<T> {
clone(&self) -> OnceCell<T>91     fn clone(&self) -> OnceCell<T> {
92         OnceCell::new_with(self.get().cloned())
93     }
94 }
95 
96 impl<T: PartialEq> PartialEq for OnceCell<T> {
eq(&self, other: &OnceCell<T>) -> bool97     fn eq(&self, other: &OnceCell<T>) -> bool {
98         self.get() == other.get()
99     }
100 }
101 
102 impl<T: Eq> Eq for OnceCell<T> {}
103 
104 impl<T> Drop for OnceCell<T> {
drop(&mut self)105     fn drop(&mut self) {
106         if self.initialized_mut() {
107             unsafe {
108                 self.value
109                     .with_mut(|ptr| ptr::drop_in_place((*ptr).as_mut_ptr()));
110             };
111         }
112     }
113 }
114 
115 impl<T> From<T> for OnceCell<T> {
from(value: T) -> Self116     fn from(value: T) -> Self {
117         OnceCell {
118             value_set: AtomicBool::new(true),
119             value: UnsafeCell::new(MaybeUninit::new(value)),
120             semaphore: Semaphore::new_closed(),
121         }
122     }
123 }
124 
125 impl<T> OnceCell<T> {
126     /// Creates a new empty `OnceCell` instance.
new() -> Self127     pub fn new() -> Self {
128         OnceCell {
129             value_set: AtomicBool::new(false),
130             value: UnsafeCell::new(MaybeUninit::uninit()),
131             semaphore: Semaphore::new(1),
132         }
133     }
134 
135     /// Creates a new `OnceCell` that contains the provided value, if any.
136     ///
137     /// If the `Option` is `None`, this is equivalent to `OnceCell::new`.
138     ///
139     /// [`OnceCell::new`]: crate::sync::OnceCell::new
140     // Once https://github.com/rust-lang/rust/issues/73255 lands
141     // and tokio MSRV is bumped to the rustc version with it stablised,
142     // we can made this function available in const context,
143     // by creating `Semaphore::const_new_closed`.
new_with(value: Option<T>) -> Self144     pub fn new_with(value: Option<T>) -> Self {
145         if let Some(v) = value {
146             OnceCell::from(v)
147         } else {
148             OnceCell::new()
149         }
150     }
151 
152     /// Creates a new empty `OnceCell` instance.
153     ///
154     /// Equivalent to `OnceCell::new`, except that it can be used in static
155     /// variables.
156     ///
157     /// # Example
158     ///
159     /// ```
160     /// use tokio::sync::OnceCell;
161     ///
162     /// static ONCE: OnceCell<u32> = OnceCell::const_new();
163     ///
164     /// async fn get_global_integer() -> &'static u32 {
165     ///     ONCE.get_or_init(|| async {
166     ///         1 + 1
167     ///     }).await
168     /// }
169     ///
170     /// #[tokio::main]
171     /// async fn main() {
172     ///     let result = get_global_integer().await;
173     ///     assert_eq!(*result, 2);
174     /// }
175     /// ```
176     #[cfg(not(all(loom, test)))]
const_new() -> Self177     pub const fn const_new() -> Self {
178         OnceCell {
179             value_set: AtomicBool::new(false),
180             value: UnsafeCell::new(MaybeUninit::uninit()),
181             semaphore: Semaphore::const_new(1),
182         }
183     }
184 
185     /// Returns `true` if the `OnceCell` currently contains a value, and `false`
186     /// otherwise.
initialized(&self) -> bool187     pub fn initialized(&self) -> bool {
188         // Using acquire ordering so any threads that read a true from this
189         // atomic is able to read the value.
190         self.value_set.load(Ordering::Acquire)
191     }
192 
193     /// Returns `true` if the `OnceCell` currently contains a value, and `false`
194     /// otherwise.
initialized_mut(&mut self) -> bool195     fn initialized_mut(&mut self) -> bool {
196         *self.value_set.get_mut()
197     }
198 
199     // SAFETY: The OnceCell must not be empty.
get_unchecked(&self) -> &T200     unsafe fn get_unchecked(&self) -> &T {
201         &*self.value.with(|ptr| (*ptr).as_ptr())
202     }
203 
204     // SAFETY: The OnceCell must not be empty.
get_unchecked_mut(&mut self) -> &mut T205     unsafe fn get_unchecked_mut(&mut self) -> &mut T {
206         &mut *self.value.with_mut(|ptr| (*ptr).as_mut_ptr())
207     }
208 
set_value(&self, value: T, permit: SemaphorePermit<'_>) -> &T209     fn set_value(&self, value: T, permit: SemaphorePermit<'_>) -> &T {
210         // SAFETY: We are holding the only permit on the semaphore.
211         unsafe {
212             self.value.with_mut(|ptr| (*ptr).as_mut_ptr().write(value));
213         }
214 
215         // Using release ordering so any threads that read a true from this
216         // atomic is able to read the value we just stored.
217         self.value_set.store(true, Ordering::Release);
218         self.semaphore.close();
219         permit.forget();
220 
221         // SAFETY: We just initialized the cell.
222         unsafe { self.get_unchecked() }
223     }
224 
225     /// Returns a reference to the value currently stored in the `OnceCell`, or
226     /// `None` if the `OnceCell` is empty.
get(&self) -> Option<&T>227     pub fn get(&self) -> Option<&T> {
228         if self.initialized() {
229             Some(unsafe { self.get_unchecked() })
230         } else {
231             None
232         }
233     }
234 
235     /// Returns a mutable reference to the value currently stored in the
236     /// `OnceCell`, or `None` if the `OnceCell` is empty.
237     ///
238     /// Since this call borrows the `OnceCell` mutably, it is safe to mutate the
239     /// value inside the `OnceCell` — the mutable borrow statically guarantees
240     /// no other references exist.
get_mut(&mut self) -> Option<&mut T>241     pub fn get_mut(&mut self) -> Option<&mut T> {
242         if self.initialized_mut() {
243             Some(unsafe { self.get_unchecked_mut() })
244         } else {
245             None
246         }
247     }
248 
249     /// Sets the value of the `OnceCell` to the given value if the `OnceCell` is
250     /// empty.
251     ///
252     /// If the `OnceCell` already has a value, this call will fail with an
253     /// [`SetError::AlreadyInitializedError`].
254     ///
255     /// If the `OnceCell` is empty, but some other task is currently trying to
256     /// set the value, this call will fail with [`SetError::InitializingError`].
257     ///
258     /// [`SetError::AlreadyInitializedError`]: crate::sync::SetError::AlreadyInitializedError
259     /// [`SetError::InitializingError`]: crate::sync::SetError::InitializingError
set(&self, value: T) -> Result<(), SetError<T>>260     pub fn set(&self, value: T) -> Result<(), SetError<T>> {
261         if self.initialized() {
262             return Err(SetError::AlreadyInitializedError(value));
263         }
264 
265         // Another task might be initializing the cell, in which case
266         // `try_acquire` will return an error. If we succeed to acquire the
267         // permit, then we can set the value.
268         match self.semaphore.try_acquire() {
269             Ok(permit) => {
270                 debug_assert!(!self.initialized());
271                 self.set_value(value, permit);
272                 Ok(())
273             }
274             Err(TryAcquireError::NoPermits) => {
275                 // Some other task is holding the permit. That task is
276                 // currently trying to initialize the value.
277                 Err(SetError::InitializingError(value))
278             }
279             Err(TryAcquireError::Closed) => {
280                 // The semaphore was closed. Some other task has initialized
281                 // the value.
282                 Err(SetError::AlreadyInitializedError(value))
283             }
284         }
285     }
286 
287     /// Gets the value currently in the `OnceCell`, or initialize it with the
288     /// given asynchronous operation.
289     ///
290     /// If some other task is currently working on initializing the `OnceCell`,
291     /// this call will wait for that other task to finish, then return the value
292     /// that the other task produced.
293     ///
294     /// If the provided operation is cancelled or panics, the initialization
295     /// attempt is cancelled. If there are other tasks waiting for the value to
296     /// be initialized, one of them will start another attempt at initializing
297     /// the value.
298     ///
299     /// This will deadlock if `f` tries to initialize the cell recursively.
get_or_init<F, Fut>(&self, f: F) -> &T where F: FnOnce() -> Fut, Fut: Future<Output = T>,300     pub async fn get_or_init<F, Fut>(&self, f: F) -> &T
301     where
302         F: FnOnce() -> Fut,
303         Fut: Future<Output = T>,
304     {
305         crate::trace::async_trace_leaf().await;
306 
307         if self.initialized() {
308             // SAFETY: The OnceCell has been fully initialized.
309             unsafe { self.get_unchecked() }
310         } else {
311             // Here we try to acquire the semaphore permit. Holding the permit
312             // will allow us to set the value of the OnceCell, and prevents
313             // other tasks from initializing the OnceCell while we are holding
314             // it.
315             match self.semaphore.acquire().await {
316                 Ok(permit) => {
317                     debug_assert!(!self.initialized());
318 
319                     // If `f()` panics or `select!` is called, this
320                     // `get_or_init` call is aborted and the semaphore permit is
321                     // dropped.
322                     let value = f().await;
323 
324                     self.set_value(value, permit)
325                 }
326                 Err(_) => {
327                     debug_assert!(self.initialized());
328 
329                     // SAFETY: The semaphore has been closed. This only happens
330                     // when the OnceCell is fully initialized.
331                     unsafe { self.get_unchecked() }
332                 }
333             }
334         }
335     }
336 
337     /// Gets the value currently in the `OnceCell`, or initialize it with the
338     /// given asynchronous operation.
339     ///
340     /// If some other task is currently working on initializing the `OnceCell`,
341     /// this call will wait for that other task to finish, then return the value
342     /// that the other task produced.
343     ///
344     /// If the provided operation returns an error, is cancelled or panics, the
345     /// initialization attempt is cancelled. If there are other tasks waiting
346     /// for the value to be initialized, one of them will start another attempt
347     /// at initializing the value.
348     ///
349     /// This will deadlock if `f` tries to initialize the cell recursively.
get_or_try_init<E, F, Fut>(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Fut, Fut: Future<Output = Result<T, E>>,350     pub async fn get_or_try_init<E, F, Fut>(&self, f: F) -> Result<&T, E>
351     where
352         F: FnOnce() -> Fut,
353         Fut: Future<Output = Result<T, E>>,
354     {
355         crate::trace::async_trace_leaf().await;
356 
357         if self.initialized() {
358             // SAFETY: The OnceCell has been fully initialized.
359             unsafe { Ok(self.get_unchecked()) }
360         } else {
361             // Here we try to acquire the semaphore permit. Holding the permit
362             // will allow us to set the value of the OnceCell, and prevents
363             // other tasks from initializing the OnceCell while we are holding
364             // it.
365             match self.semaphore.acquire().await {
366                 Ok(permit) => {
367                     debug_assert!(!self.initialized());
368 
369                     // If `f()` panics or `select!` is called, this
370                     // `get_or_try_init` call is aborted and the semaphore
371                     // permit is dropped.
372                     let value = f().await;
373 
374                     match value {
375                         Ok(value) => Ok(self.set_value(value, permit)),
376                         Err(e) => Err(e),
377                     }
378                 }
379                 Err(_) => {
380                     debug_assert!(self.initialized());
381 
382                     // SAFETY: The semaphore has been closed. This only happens
383                     // when the OnceCell is fully initialized.
384                     unsafe { Ok(self.get_unchecked()) }
385                 }
386             }
387         }
388     }
389 
390     /// Takes the value from the cell, destroying the cell in the process.
391     /// Returns `None` if the cell is empty.
into_inner(mut self) -> Option<T>392     pub fn into_inner(mut self) -> Option<T> {
393         if self.initialized_mut() {
394             // Set to uninitialized for the destructor of `OnceCell` to work properly
395             *self.value_set.get_mut() = false;
396             Some(unsafe { self.value.with(|ptr| ptr::read(ptr).assume_init()) })
397         } else {
398             None
399         }
400     }
401 
402     /// Takes ownership of the current value, leaving the cell empty.  Returns
403     /// `None` if the cell is empty.
take(&mut self) -> Option<T>404     pub fn take(&mut self) -> Option<T> {
405         std::mem::take(self).into_inner()
406     }
407 }
408 
409 // Since `get` gives us access to immutable references of the OnceCell, OnceCell
410 // can only be Sync if T is Sync, otherwise OnceCell would allow sharing
411 // references of !Sync values across threads. We need T to be Send in order for
412 // OnceCell to by Sync because we can use `set` on `&OnceCell<T>` to send values
413 // (of type T) across threads.
414 unsafe impl<T: Sync + Send> Sync for OnceCell<T> {}
415 
416 // Access to OnceCell's value is guarded by the semaphore permit
417 // and atomic operations on `value_set`, so as long as T itself is Send
418 // it's safe to send it to another thread
419 unsafe impl<T: Send> Send for OnceCell<T> {}
420 
421 /// Errors that can be returned from [`OnceCell::set`].
422 ///
423 /// [`OnceCell::set`]: crate::sync::OnceCell::set
424 #[derive(Debug, PartialEq, Eq)]
425 pub enum SetError<T> {
426     /// The cell was already initialized when [`OnceCell::set`] was called.
427     ///
428     /// [`OnceCell::set`]: crate::sync::OnceCell::set
429     AlreadyInitializedError(T),
430 
431     /// The cell is currently being initialized.
432     InitializingError(T),
433 }
434 
435 impl<T> fmt::Display for SetError<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result436     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
437         match self {
438             SetError::AlreadyInitializedError(_) => write!(f, "AlreadyInitializedError"),
439             SetError::InitializingError(_) => write!(f, "InitializingError"),
440         }
441     }
442 }
443 
444 impl<T: fmt::Debug> Error for SetError<T> {}
445 
446 impl<T> SetError<T> {
447     /// Whether `SetError` is `SetError::AlreadyInitializedError`.
is_already_init_err(&self) -> bool448     pub fn is_already_init_err(&self) -> bool {
449         match self {
450             SetError::AlreadyInitializedError(_) => true,
451             SetError::InitializingError(_) => false,
452         }
453     }
454 
455     /// Whether `SetError` is `SetError::InitializingError`
is_initializing_err(&self) -> bool456     pub fn is_initializing_err(&self) -> bool {
457         match self {
458             SetError::AlreadyInitializedError(_) => false,
459             SetError::InitializingError(_) => true,
460         }
461     }
462 }
463