@@ -384,6 +384,133 @@ in (atomicPtrIsProperlyAligned(here), "Argument `here` is not properly aligned")
384384 return atomicCompareExchangeStrong! (succ, fail)(cast (T* )here, cast (T* )ifThis, cast (V)writeThis);
385385}
386386
387+ /**
388+ * Stores 'writeThis' to the memory referenced by 'here' if the value
389+ * referenced by 'here' is equal to 'ifThis'.
390+ * The 'weak' version of cas may spuriously fail. It is recommended to
391+ * use `casWeak` only when `cas` would be used in a loop.
392+ * This operation is both
393+ * lock-free and atomic.
394+ *
395+ * Params:
396+ * here = The address of the destination variable.
397+ * writeThis = The value to store.
398+ * ifThis = The comparison value.
399+ *
400+ * Returns:
401+ * true if the store occurred, false if not.
402+ */
403+ bool casWeak (MemoryOrder succ = MemoryOrder.seq,MemoryOrder fail = MemoryOrder.seq,T,V1 ,V2 )(T* here, V1 ifThis, V2 writeThis) pure nothrow @nogc @trusted
404+ if (! is (T == shared S, S) && is (T : V1 ))
405+ in (atomicPtrIsProperlyAligned(here), " Argument `here` is not properly aligned" )
406+ {
407+ // resolve implicit conversions
408+ T arg1 = ifThis;
409+ T arg2 = writeThis;
410+
411+ static if (__traits(isFloating, T))
412+ {
413+ alias IntTy = IntForFloat! T;
414+ return atomicCompareExchangeWeakNoResult! (succ, fail)(cast (IntTy* )here, * cast (IntTy* )&arg1, * cast (IntTy* )&arg2);
415+ }
416+ else
417+ return atomicCompareExchangeWeakNoResult! (succ, fail)(here, arg1, arg2);
418+ }
419+
420+ // / Ditto
421+ bool casWeak (MemoryOrder succ = MemoryOrder.seq,MemoryOrder fail = MemoryOrder.seq,T,V1 ,V2 )(shared (T)* here, V1 ifThis, V2 writeThis) pure nothrow @nogc @trusted
422+ if (! is (T == class ) && (is (T : V1 ) || is (shared T : V1 )))
423+ in (atomicPtrIsProperlyAligned(here), " Argument `here` is not properly aligned" )
424+ {
425+ static if (is (V1 == shared U1 , U1 ))
426+ alias Thunk1 = U1 ;
427+ else
428+ alias Thunk1 = V1 ;
429+ static if (is (V2 == shared U2 , U2 ))
430+ alias Thunk2 = U2 ;
431+ else
432+ {
433+ import core.internal.traits : hasUnsharedIndirections;
434+ static assert (! hasUnsharedIndirections! V2 , " Copying `" ~ V2 .stringof ~ " * writeThis` to `" ~ shared (T).stringof ~ " * here` would violate shared." );
435+ alias Thunk2 = V2 ;
436+ }
437+ return casWeak! (succ, fail)(cast (T* )here, * cast (Thunk1* )&ifThis, * cast (Thunk2* )&writeThis);
438+ }
439+
440+ // / Ditto
441+ bool casWeak (MemoryOrder succ = MemoryOrder.seq,MemoryOrder fail = MemoryOrder.seq,T,V1 ,V2 )(shared (T)* here, shared (V1 ) ifThis, shared (V2 ) writeThis) pure nothrow @nogc @trusted
442+ if (is (T == class ))
443+ in (atomicPtrIsProperlyAligned(here), " Argument `here` is not properly aligned" )
444+ {
445+ return atomicCompareExchangeWeakNoResult! (succ, fail)(cast (T* )here, cast (V1 )ifThis, cast (V2 )writeThis);
446+ }
447+
448+ /**
449+ * Stores 'writeThis' to the memory referenced by 'here' if the value
450+ * referenced by 'here' is equal to the value referenced by 'ifThis'.
451+ * The prior value referenced by 'here' is written to `ifThis` and
452+ * returned to the user.
453+ * The 'weak' version of cas may spuriously fail. It is recommended to
454+ * use `casWeak` only when `cas` would be used in a loop.
455+ * This operation is both lock-free and atomic.
456+ *
457+ * Params:
458+ * here = The address of the destination variable.
459+ * writeThis = The value to store.
460+ * ifThis = The address of the value to compare, and receives the prior value of `here` as output.
461+ *
462+ * Returns:
463+ * true if the store occurred, false if not.
464+ */
465+ bool casWeak (MemoryOrder succ = MemoryOrder.seq,MemoryOrder fail = MemoryOrder.seq,T,V)(T* here, T* ifThis, V writeThis) pure nothrow @nogc @trusted
466+ if (! is (T == shared S, S) && ! is (V == shared U, U))
467+ in (atomicPtrIsProperlyAligned(here), " Argument `here` is not properly aligned" )
468+ {
469+ // resolve implicit conversions
470+ T arg1 = writeThis;
471+
472+ static if (__traits(isFloating, T))
473+ {
474+ alias IntTy = IntForFloat! T;
475+ return atomicCompareExchangeWeak! (succ, fail)(cast (IntTy* )here, cast (IntTy* )ifThis, * cast (IntTy* )&writeThis);
476+ }
477+ else
478+ return atomicCompareExchangeWeak! (succ, fail)(here, ifThis, writeThis);
479+ }
480+
481+ // / Ditto
482+ bool casWeak (MemoryOrder succ = MemoryOrder.seq,MemoryOrder fail = MemoryOrder.seq,T,V1 ,V2 )(shared (T)* here, V1 * ifThis, V2 writeThis) pure nothrow @nogc @trusted
483+ if (! is (T == class ) && (is (T : V1 ) || is (shared T : V1 )))
484+ in (atomicPtrIsProperlyAligned(here), " Argument `here` is not properly aligned" )
485+ {
486+ static if (is (V1 == shared U1 , U1 ))
487+ alias Thunk1 = U1 ;
488+ else
489+ {
490+ import core.internal.traits : hasUnsharedIndirections;
491+ static assert (! hasUnsharedIndirections! V1 , " Copying `" ~ shared (T).stringof ~ " * here` to `" ~ V1 .stringof ~ " * ifThis` would violate shared." );
492+ alias Thunk1 = V1 ;
493+ }
494+ static if (is (V2 == shared U2 , U2 ))
495+ alias Thunk2 = U2 ;
496+ else
497+ {
498+ import core.internal.traits : hasUnsharedIndirections;
499+ static assert (! hasUnsharedIndirections! V2 , " Copying `" ~ V2 .stringof ~ " * writeThis` to `" ~ shared (T).stringof ~ " * here` would violate shared." );
500+ alias Thunk2 = V2 ;
501+ }
502+ static assert (is (T : Thunk1), " Mismatching types for `here` and `ifThis`: `" ~ shared (T).stringof ~ " ` and `" ~ V1 .stringof ~ " `." );
503+ return casWeak! (succ, fail)(cast (T* )here, cast (Thunk1* )ifThis, * cast (Thunk2* )&writeThis);
504+ }
505+
506+ // / Ditto
507+ bool casWeak (MemoryOrder succ = MemoryOrder.seq,MemoryOrder fail = MemoryOrder.seq,T,V)(shared (T)* here, shared (T)* ifThis, shared (V) writeThis) pure nothrow @nogc @trusted
508+ if (is (T == class ))
509+ in (atomicPtrIsProperlyAligned(here), " Argument `here` is not properly aligned" )
510+ {
511+ return atomicCompareExchangeWeak! (succ, fail)(cast (T* )here, cast (T* )ifThis, cast (V)writeThis);
512+ }
513+
387514/**
388515 * Inserts a full load/store memory fence (on platforms that need it). This ensures
389516 * that all loads and stores before a call to this function are executed before any
@@ -445,7 +572,7 @@ in (atomicValueIsProperlyAligned(val))
445572 {
446573 set = get ;
447574 mixin (" set " ~ op ~ " mod;" );
448- } while (! casByRef (val, get , set));
575+ } while (! casWeakByRef (val, get , set));
449576 return set;
450577 }
451578 else
@@ -539,9 +666,9 @@ private
539666 }
540667
541668 // TODO: it'd be nice if we had @trusted scopes; we could remove this...
542- bool casByRef (T,V1 ,V2 )(ref T value, V1 ifThis, V2 writeThis) pure nothrow @nogc @trusted
669+ bool casWeakByRef (T,V1 ,V2 )(ref T value, ref V1 ifThis, V2 writeThis) pure nothrow @nogc @trusted
543670 {
544- return cas (&value, ifThis, writeThis);
671+ return casWeak (&value, & ifThis, writeThis);
545672 }
546673
547674 /* Construct a type with a shared tail, and if possible with an unshared
0 commit comments