@@ -432,6 +432,48 @@ It is possible to add only `sync` version of the types, as they are the most use
432
432
However , this would be against zero cost abstractions spirit .
433
433
Additionally , non thread - safe version is required to replace `thread_local ! ` macro without imposing synchronization .
434
434
435
+ ## Synchronization Guarantees
436
+
437
+ In theory , it is possible to specify two different synchronization guarantees for `get ` operation , release / acquire or release / consume .
438
+ They differ in how they treat side effects .
439
+ If thread * * A ** executes `get_or_init (f )`, and thread * * B ** executes `get ` and observes the value , release / acquire guarantees that * * B ** also observes side - effects of `f `.
440
+
441
+ Here 's a program which allows to observe the difference :
442
+
443
+ ```rust
444
+ static FLAG : AtomicBool = AtomicBool :: new (false );
445
+ static CELL : OnceCell <()> = OnceCell :: new ();
446
+
447
+ // thread1
448
+ CELL . get_or_init(|| FLAG . store(true , Relaxed ));
449
+
450
+ // thread2
451
+ if CELL . get(). is_some() {
452
+ assert ! (FLAG . load(Relaxed ))
453
+ }
454
+ ```
455
+
456
+ Under release / acquire , the assert never fires .
457
+ Under release / consume , it might fire .
458
+
459
+ Release / consume can potentially be implemented more efficiently on weak memory model architectures .
460
+ However , the situation with `consume ` ordering is cloudy right now :
461
+
462
+ * [nobody knows what it actually means ](http : // www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0371r0.html),
463
+ * [but people rely on it in practice for performance ](https : // docs.rs/crossbeam-utils/0.7.0/crossbeam_utils/atomic/trait.AtomicConsume.html#tymethod.load_consume).
464
+
465
+ We can do one of the following :
466
+
467
+ 1 . Specify and implement `acquire ` ordering ,
468
+ 2 . Specify `consume ` but implement `acquire ` (or hack `consume ` in an implementation - defined manner ) with the hope to make implementation more efficient later .
469
+ 3 . Specify and implement `acquire `, but provide additional API which can take `Ordering ` as an argument .
470
+
471
+ Option two seems the most promising :
472
+
473
+ * it is forward compatible with specifying `acquire ` later ,
474
+ * for typical `OnceCell ` use - cases , `consume ` should be enough .
475
+ For guaranteeing side effects , `std :: sync :: Once ` may be used instead .
476
+
435
477
# Prior art
436
478
[prior - art ]: #prior - art
437
479
@@ -453,6 +495,7 @@ This design doesn't always work in Rust, as closing over `self` runs afoul of th
453
495
- What is the best naming / place for these types ?
454
496
- What is the best naming scheme for methods ? Is it `get_or_try_init ` or `try_inert_with `?
455
497
- Is the `F = fn () -> T ` hack worth it ?
498
+ - Which synchronization guarantee should we pick ?
456
499
457
500
# Future possibilities
458
501
[future - possibilities ]: #future - possibilities
0 commit comments