@@ -252,6 +252,50 @@ impl<T> OnceLock<T> {
252
252
}
253
253
}
254
254
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
+
255
299
/// Gets the contents of the cell, initializing it with `f` if
256
300
/// the cell was empty. If the cell was empty and `f` failed, an
257
301
/// error is returned.
@@ -303,6 +347,59 @@ impl<T> OnceLock<T> {
303
347
Ok ( unsafe { self . get_unchecked ( ) } )
304
348
}
305
349
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
+
306
403
/// Consumes the `OnceLock`, returning the wrapped value. Returns
307
404
/// `None` if the cell was empty.
308
405
///
0 commit comments