Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit fbf560c

Browse files
committed
Add casWeak, because that's the one you usually want.
1 parent 1bd60a7 commit fbf560c

File tree

1 file changed

+130
-3
lines changed

1 file changed

+130
-3
lines changed

src/core/atomic.d

Lines changed: 130 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)