1
1
use super :: { Notify , SetError } ;
2
- use crate :: { loom:: cell:: UnsafeCell , pin} ;
2
+ use crate :: {
3
+ loom:: { cell:: UnsafeCell , sync:: Mutex } ,
4
+ pin,
5
+ } ;
3
6
use std:: fmt;
4
7
use std:: mem:: MaybeUninit ;
5
8
use std:: ops:: Drop ;
6
9
use std:: ptr;
7
10
use std:: sync:: atomic:: { AtomicBool , Ordering } ;
8
- use std:: sync:: Mutex ;
9
11
10
12
// This file contains an implementation of an SetOnce. The value of SetOnce
11
13
// can only be modified once during initialization.
@@ -181,7 +183,7 @@ impl<T> SetOnce<T> {
181
183
value_set : AtomicBool :: new ( false ) ,
182
184
value : UnsafeCell :: new ( MaybeUninit :: uninit ( ) ) ,
183
185
notify : Notify :: const_new ( ) ,
184
- lock : Mutex :: new ( ( ) ) ,
186
+ lock : Mutex :: const_new ( ( ) ) ,
185
187
}
186
188
}
187
189
@@ -232,7 +234,7 @@ impl<T> SetOnce<T> {
232
234
value_set : AtomicBool :: new ( true ) ,
233
235
value : UnsafeCell :: new ( MaybeUninit :: new ( value) ) ,
234
236
notify : Notify :: const_new ( ) ,
235
- lock : Mutex :: new ( ( ) ) ,
237
+ lock : Mutex :: const_new ( ( ) ) ,
236
238
}
237
239
}
238
240
@@ -271,6 +273,10 @@ impl<T> SetOnce<T> {
271
273
self . value . with_mut ( |ptr| ( * ptr) . as_mut_ptr ( ) . write ( value) ) ;
272
274
}
273
275
276
+ // Using release ordering so any threads that read a true from this
277
+ // atomic is able to read the value we just stored.
278
+ self . value_set . store ( true , Ordering :: Release ) ;
279
+
274
280
// notify the waiting wakers that the value is set
275
281
self . notify . notify_waiters ( ) ;
276
282
}
@@ -293,29 +299,13 @@ impl<T> SetOnce<T> {
293
299
294
300
// SAFETY: lock the mutex to ensure only one caller of set
295
301
// can run at a time.
296
- match self . lock . lock ( ) {
297
- Ok ( _) => {
298
- // Using release ordering so any threads that read a true from this
299
- // atomic is able to read the value we just stored.
300
- if !self . value_set . swap ( true , Ordering :: Release ) {
301
- // SAFETY: We are swapping the value_set AtomicBool from FALSE to
302
- // TRUE with it being previously false and followed by that we are
303
- // initializing the unsafe Cell field with the value
304
- unsafe {
305
- self . set_value ( value) ;
306
- }
302
+ let _ = self . lock . lock ( ) ;
307
303
308
- Ok ( ( ) )
309
- } else {
310
- Err ( SetError :: AlreadyInitializedError ( value) )
311
- }
312
- }
313
- Err ( _) => {
314
- // If we failed to lock the mutex, it means some other task is
315
- // trying to set the value, so we return an error.
316
- Err ( SetError :: InitializingError ( value) )
317
- }
304
+ unsafe {
305
+ self . set_value ( value) ;
318
306
}
307
+
308
+ Ok ( ( ) )
319
309
}
320
310
321
311
/// Takes the value from the cell, destroying the cell in the process.
@@ -341,41 +331,28 @@ impl<T> SetOnce<T> {
341
331
/// the `SetOnce` is initialized.
342
332
///
343
333
/// If the `SetOnce` is already initialized, it will return the value
344
- // immediately.
334
+ /// immediately.
345
335
///
346
336
/// # Panics
347
337
///
348
338
/// If the `SetOnce` is not initialized after waiting, it will panic. To
349
339
/// avoid this, use `get_wait()` which returns an `Option<&T>` instead of
350
340
/// `&T`.
351
341
pub async fn wait ( & self ) -> & T {
352
- match self . get_wait ( ) . await {
353
- Some ( val) => val,
354
- _ => panic ! ( "SetOnce::wait called but the SetOnce is not initialized" ) ,
355
- }
356
- }
357
-
358
- /// Waits until set is called.
359
- ///
360
- /// If the state failed to initalize it will return `None`.
361
- pub async fn get_wait ( & self ) -> Option < & T > {
362
342
let notify_fut = self . notify . notified ( ) ;
363
343
pin ! ( notify_fut) ;
364
344
365
345
if self . value_set . load ( Ordering :: Acquire ) {
366
346
// SAFETY: the state is initialized
367
- return Some ( unsafe { self . get_unchecked ( ) } ) ;
347
+ return unsafe { self . get_unchecked ( ) } ;
368
348
}
349
+
369
350
// wait until the value is set
370
351
( & mut notify_fut) . await ;
371
352
372
- // look at the state again
373
- if self . value_set . load ( Ordering :: Acquire ) {
374
- // SAFETY: the state is initialized
375
- return Some ( unsafe { self . get_unchecked ( ) } ) ;
376
- }
377
-
378
- None
353
+ // SAFETY: Its not possible for the state to initialize after
354
+ // waker is notified
355
+ unsafe { self . get_unchecked ( ) }
379
356
}
380
357
}
381
358
0 commit comments