@@ -432,6 +432,48 @@ It is possible to add only `sync` version of the types, as they are the most use
432432However , this would be against zero cost abstractions spirit .
433433Additionally , non thread - safe version is required to replace `thread_local ! ` macro without imposing synchronization .
434434
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+
435477# Prior art
436478[prior - art ]: #prior - art
437479
@@ -453,6 +495,7 @@ This design doesn't always work in Rust, as closing over `self` runs afoul of th
453495- What is the best naming / place for these types ?
454496- What is the best naming scheme for methods ? Is it `get_or_try_init ` or `try_inert_with `?
455497- Is the `F = fn () -> T ` hack worth it ?
498+ - Which synchronization guarantee should we pick ?
456499
457500# Future possibilities
458501[future - possibilities ]: #future - possibilities
0 commit comments