@@ -384,6 +384,133 @@ in (atomicPtrIsProperlyAligned(here), "Argument `here` is not properly aligned")
384
384
return atomicCompareExchangeStrong! (succ, fail)(cast (T* )here, cast (T* )ifThis, cast (V)writeThis);
385
385
}
386
386
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
+
387
514
/**
388
515
* Inserts a full load/store memory fence (on platforms that need it). This ensures
389
516
* that all loads and stores before a call to this function are executed before any
@@ -445,7 +572,7 @@ in (atomicValueIsProperlyAligned(val))
445
572
{
446
573
set = get ;
447
574
mixin (" set " ~ op ~ " mod;" );
448
- } while (! casByRef (val, get , set));
575
+ } while (! casWeakByRef (val, get , set));
449
576
return set;
450
577
}
451
578
else
@@ -539,9 +666,9 @@ private
539
666
}
540
667
541
668
// 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
543
670
{
544
- return cas (&value, ifThis, writeThis);
671
+ return casWeak (&value, & ifThis, writeThis);
545
672
}
546
673
547
674
/* Construct a type with a shared tail, and if possible with an unshared
0 commit comments