@@ -252,6 +252,50 @@ impl<T> OnceLock<T> {
252252 }
253253 }
254254
255+ /// Gets the mutable reference of the contents of the cell, initializing
256+ /// it with `f` if the cell was empty.
257+ ///
258+ /// Many threads may call `get_mut_or_init` concurrently with different
259+ /// initializing functions, but it is guaranteed that only one function
260+ /// will be executed.
261+ ///
262+ /// # Panics
263+ ///
264+ /// If `f` panics, the panic is propagated to the caller, and the cell
265+ /// remains uninitialized.
266+ ///
267+ /// It is an error to reentrantly initialize the cell from `f`. The
268+ /// exact outcome is unspecified. Current implementation deadlocks, but
269+ /// this may be changed to a panic in the future.
270+ ///
271+ /// # Examples
272+ ///
273+ /// ```
274+ /// #![feature(once_cell_get_mut)]
275+ ///
276+ /// use std::sync::OnceLock;
277+ ///
278+ /// let mut cell = OnceLock::new();
279+ /// let value = cell.get_mut_or_init(|| 92);
280+ /// assert_eq!(*value, 92);
281+ ///
282+ /// *value += 2;
283+ /// assert_eq!(*value, 94);
284+ ///
285+ /// let value = cell.get_mut_or_init(|| unreachable!());
286+ /// assert_eq!(*value, 94);
287+ /// ```
288+ #[ inline]
289+ #[ unstable( feature = "once_cell_get_mut" , issue = "121641" ) ]
290+ pub fn get_mut_or_init < F > ( & mut self , f : F ) -> & mut T
291+ where
292+ F : FnOnce ( ) -> T ,
293+ {
294+ match self . get_mut_or_try_init ( || Ok :: < T , !> ( f ( ) ) ) {
295+ Ok ( val) => val,
296+ }
297+ }
298+
255299 /// Gets the contents of the cell, initializing it with `f` if
256300 /// the cell was empty. If the cell was empty and `f` failed, an
257301 /// error is returned.
@@ -303,6 +347,59 @@ impl<T> OnceLock<T> {
303347 Ok ( unsafe { self . get_unchecked ( ) } )
304348 }
305349
350+ /// Gets the mutable reference of the contents of the cell, initializing
351+ /// it with `f` if the cell was empty. If the cell was empty and `f` failed,
352+ /// an error is returned.
353+ ///
354+ /// # Panics
355+ ///
356+ /// If `f` panics, the panic is propagated to the caller, and
357+ /// the cell remains uninitialized.
358+ ///
359+ /// It is an error to reentrantly initialize the cell from `f`.
360+ /// The exact outcome is unspecified. Current implementation
361+ /// deadlocks, but this may be changed to a panic in the future.
362+ ///
363+ /// # Examples
364+ ///
365+ /// ```
366+ /// #![feature(once_cell_get_mut)]
367+ ///
368+ /// use std::sync::OnceLock;
369+ ///
370+ /// let mut cell: OnceLock<u32> = OnceLock::new();
371+ ///
372+ /// // Failed initializers do not change the value
373+ /// assert!(cell.get_mut_or_try_init(|| "not a number!".parse()).is_err());
374+ /// assert!(cell.get().is_none());
375+ ///
376+ /// let value = cell.get_mut_or_try_init(|| "1234".parse());
377+ /// assert_eq!(value, Ok(&mut 1234));
378+ /// *value.unwrap() += 2;
379+ /// assert_eq!(cell.get(), Some(&1236))
380+ /// ```
381+ #[ inline]
382+ #[ unstable( feature = "once_cell_get_mut" , issue = "121641" ) ]
383+ pub fn get_mut_or_try_init < F , E > ( & mut self , f : F ) -> Result < & mut T , E >
384+ where
385+ F : FnOnce ( ) -> Result < T , E > ,
386+ {
387+ // Fast path check
388+ // NOTE: We need to perform an acquire on the state in this method
389+ // in order to correctly synchronize `LazyLock::force`. This is
390+ // currently done by calling `self.get()`, which in turn calls
391+ // `self.is_initialized()`, which in turn performs the acquire.
392+ if let Some ( value) = self . get_mut ( ) {
393+ return Ok ( value) ;
394+ }
395+ self . initialize ( f) ?;
396+
397+ debug_assert ! ( self . is_initialized( ) ) ;
398+
399+ // SAFETY: The inner value has been initialized
400+ Ok ( unsafe { self . get_unchecked_mut ( ) } )
401+ }
402+
306403 /// Consumes the `OnceLock`, returning the wrapped value. Returns
307404 /// `None` if the cell was empty.
308405 ///
0 commit comments