-
-
Notifications
You must be signed in to change notification settings - Fork 411
Improve core.atomic.cas documentation, formatting, and constraints
#3094
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -264,20 +264,35 @@ in (atomicPtrIsProperlyAligned(here), "Argument `here` is not properly aligned") | |
| } | ||
|
|
||
| /** | ||
| * Stores 'writeThis' to the memory referenced by 'here' if the value | ||
| * referenced by 'here' is equal to 'ifThis'. This operation is both | ||
| * lock-free and atomic. | ||
| * Performs the atomic operation known as "compare-and-swap" (CAS). | ||
| * | ||
| * Compare-and-swap is essentially the following operation: | ||
| * --- | ||
| * if (*here == ifThis) | ||
| * { | ||
| * *here = writeThis; | ||
| * return true; | ||
| * } | ||
| * else | ||
| * return false; | ||
| * --- | ||
| * This operation is both lock-free and atomic. | ||
| * | ||
| * Params: | ||
| * here = The address of the destination variable. | ||
| * writeThis = The value to store. | ||
| * ifThis = The comparison value. | ||
| * | ||
| * Returns: | ||
| * true if the store occurred, false if not. | ||
| * Whether the swap occured or not. | ||
| * | ||
| * See_Also: | ||
| * https://en.wikipedia.org/wiki/Compare-and-swap | ||
| */ | ||
| bool cas(MemoryOrder succ = MemoryOrder.seq,MemoryOrder fail = MemoryOrder.seq,T,V1,V2)(T* here, V1 ifThis, V2 writeThis) pure nothrow @nogc @trusted | ||
| if (!is(T == shared) && is(T : V1)) | ||
| bool cas | ||
| (MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T, V1, V2) | ||
| (T* here, V1 ifThis, V2 writeThis) pure nothrow @nogc @trusted | ||
| if (!is(T == shared) && is(V1 : T)) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hard to tell from the diff if you made functional changes or just reformat the existing code... |
||
| in (atomicPtrIsProperlyAligned(here), "Argument `here` is not properly aligned") | ||
| { | ||
| // resolve implicit conversions | ||
|
|
@@ -294,8 +309,10 @@ in (atomicPtrIsProperlyAligned(here), "Argument `here` is not properly aligned") | |
| } | ||
|
|
||
| /// Ditto | ||
| bool cas(MemoryOrder succ = MemoryOrder.seq,MemoryOrder fail = MemoryOrder.seq,T,V1,V2)(shared(T)* here, V1 ifThis, V2 writeThis) pure nothrow @nogc @trusted | ||
| if (!is(T == class) && (is(T : V1) || is(shared T : V1))) | ||
| bool cas | ||
| (MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T, V1, V2) | ||
| (shared(T)* here, V1 ifThis, V2 writeThis) pure nothrow @nogc @trusted | ||
| if (!is(T == class) && (is(V1 : T) || is(V1 : shared T))) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh I see there is hidden changes!
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should review commit-by-commit, that will be much easier to see, and you will also see the rationale for it ;)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I'm sorry! I somehow looked at the inverse of what you're doing. So, I wonder if it's actually necessary for |
||
| in (atomicPtrIsProperlyAligned(here), "Argument `here` is not properly aligned") | ||
| { | ||
| static if (is (V1 == shared U1, U1)) | ||
|
|
@@ -1194,4 +1211,42 @@ version (CoreUnittest) | |
| shared NoIndirections n; | ||
| static assert(is(typeof(atomicLoad(n)) == NoIndirections)); | ||
| } | ||
|
|
||
| /* | ||
| * Used to trigger: | ||
| * --- | ||
| * Error: template core.atomic.cas cannot deduce function from argument types | ||
| * !()(shared(immutable(Image)*)*, typeof(null), immutable(Image*)), candidates are: | ||
| * | ||
| * cas(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T, V1, V2) | ||
| * (T* here, V1 ifThis, V2 writeThis) | ||
| * | ||
| */ | ||
| pure nothrow @safe unittest | ||
| { | ||
| // A structure that is not atomically initialization (e.g. open files) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Grammar. |
||
| static struct Image { void* ptr; } | ||
|
|
||
| // In practice, a global value | ||
| shared immutable(Image)* cache; | ||
| // Manifest constant for code clarity | ||
| immutable Sentinel = () @trusted { return cast(immutable Image*) size_t.max; }(); | ||
|
|
||
| immutable(Image)* local = atomicLoad(cache); | ||
| // Two steps initialization | ||
| if (local is null && cas(&cache, null, Sentinel)) | ||
| { | ||
| local = new immutable(Image)(null); | ||
| atomicStore(cache, local); | ||
| } | ||
| else | ||
| { | ||
| while (local is Sentinel) | ||
| { | ||
| pause(); | ||
| local = atomicLoad(cache); | ||
| } | ||
| } | ||
| // Use local | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
weird life choices
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I don't like it either, hence why I'm experimenting with: #3095