assumeLocal: convert shared lvalue to a non-shared one#724
assumeLocal: convert shared lvalue to a non-shared one#724radcapricorn wants to merge 6 commits intodlang:masterfrom
Conversation
src/core/atomic.d
Outdated
There was a problem hiding this comment.
Kill off the As the name suggests part please (we're aiming for objective documentation). :)
There was a problem hiding this comment.
If this doesn't support classes it should document this. But why doesn't it support classes? That too should be documented.
|
Something is wrong here. Why do you make something shared if it's protected by a mutex? |
|
Consider member variables inside a It's true that accessing the variable outside of the lock will be erroneous, but this function is a convenience for cases when such access is not needed. See e.g. my ongoing branch implementing Some kind of workaround is needed. Lots of casts or chains of raw atomicLoad/Store calls IMO are inferior to this little helper. |
|
What's with automatic HeadUnshared for synchronized classes? I don't want to slow down you efforts to make core.sync shared and I think |
Even if it were implemented in that exact wording, it would be of little help in many cases. I know that in the grand scheme,
I know, that is my thread :)
I'm trying to. |
src/core/atomic.d
Outdated
|
Fine, but let's call it |
|
Take that back, should be |
|
ping |
|
+1 for |
|
I apologize for so long an absence, got caught up in a no-D world. So, rename to |
|
yes please |
|
Ping |
|
@radcapricorn any chance to revive this? Seems like non-controversial stuff that just fell off the radar. |
|
Ping @radcapricorn ? |
|
Three years >< |
src/core/atomic.d
Outdated
| ref T assumeUnshared(T)(ref shared T val) @system @nogc pure nothrow | ||
| if(!is(T == class) && !is(T == interface)) | ||
| { | ||
| return *cast(T*)&val; |
There was a problem hiding this comment.
space after close paren in cast
| * Returns: | ||
| * The non-shared lvalue. | ||
| */ | ||
| ref immutable(T) assumeUnshared(T)(ref immutable(T) val) @safe @nogc pure nothrow |
There was a problem hiding this comment.
What would be a use case for this? It doesn't change the type of its argument.
There was a problem hiding this comment.
Generic code.
shared struct Example(T)
{
private T payload;
T getUnsharedCopyOfPayload() const
{
return payload.assumeUnshared;
}
}
auto createExample(T)(auto ref T value)
{
return shared(Example!T)(value);
}
immutable int i = 42;
auto example = createExample(i);
assert(is(typeof(example.getUnsharedCopyOfPayload()) == immutable(int));
This way, Example doesn't have to specialize such use case.
There was a problem hiding this comment.
IOTW, it's safe to assume immutable as unshared. But the signature ref T assumeUnshared(T)(ref shared T val) will not accept immutable lvalue, hence the specialization.
There was a problem hiding this comment.
immutable is actually implicitly shared
There was a problem hiding this comment.
Exactly, and assumeUnshared should accept shared arguments, therefore it shouldn't fail to compile with immutable argument. It works as advertised: takes shared lvalue and yields lvalue that can be treated as unshared. It just so happens that immutable is both at the same time.
There was a problem hiding this comment.
@andralex @radcapricorn anything else still not clear?
There was a problem hiding this comment.
I'm still unconvinced about the usefulness. By that logic we should also define assumeUnshared for regular data so assumeUnshared works transparently with all data types (after all unshared data can be assumed to be unshared!)
One possibility is to not introduce this overload yet, and see how necessary it is in practice.
At any rate, if we do introduce the overload the documentation must be merged with the other overload's.
andralex
left a comment
There was a problem hiding this comment.
This is a good addition. A few nits need fixing.
| ref T assumeUnshared(T)(ref shared T val) @system @nogc pure nothrow | ||
| if(!is(T == class) && !is(T == interface)) | ||
| { | ||
| return *cast(T*) &val; |
There was a problem hiding this comment.
This is the ddoc version, right? Then it should not have an implementation.
| * Returns: | ||
| * The non-shared lvalue. | ||
| */ | ||
| ref immutable(T) assumeUnshared(T)(ref immutable(T) val) @safe @nogc pure nothrow |
There was a problem hiding this comment.
I'm still unconvinced about the usefulness. By that logic we should also define assumeUnshared for regular data so assumeUnshared works transparently with all data types (after all unshared data can be assumed to be unshared!)
One possibility is to not introduce this overload yet, and see how necessary it is in practice.
At any rate, if we do introduce the overload the documentation must be merged with the other overload's.
|
|
||
| // assumeUnshared is architecture-independent: it is just a cast | ||
| ref auto assumeUnshared(T)(ref shared T val) @system @nogc pure nothrow | ||
| if(!is(T == class) && !is(T == interface)) |
There was a problem hiding this comment.
obey phobos, if flush to the left and space after it
|
Revived this to #2156 |
This is one of the two functions to satisfy ER 12133 - Relaxed read-modify-write for shared lvalues.