valid uses of shared
Steven Schveighoffer
schveiguy at yahoo.com
Mon Jun 11 07:46:43 PDT 2012
On Mon, 11 Jun 2012 09:39:40 -0400, Artur Skawina <art.08.09 at gmail.com>
wrote:
> On 06/11/12 14:07, Steven Schveighoffer wrote:
>> However, allocating another heap block to do sharing, in my opinion, is
>> worth the extra cost. This way, you have clearly separated what is
>> shared and what isn't.
>>
>> You can always cast to get around the limitations.
>
> "clearly separating what is shared and what isn't" *is* exactly what
> tagging the data with 'shared' does.
There are special GC considerations for shared as well. For instance,
unshared data can go into a "local" heap.
But I feel uneasy passing around pointers to heap data to other threads
where some of my thread-local data is present. It's bound to lead to
unwanted effects.
For example, if I share some piece of my class, and the other thread holds
onto it forever, it means my class (which may hold large resources that
aren't shared) will not be dealloced even when there's no reference to it
outside that piece of shared data.
Also, don't forget, you can cast to get the behavior you desire. You
should always be able to work around these limitations with casting (and
casting unshared to shared should be well-defined for the compiler as long
as you don't ever treat the data as unshared again, similar to immutable).
I think it's reasonable to make it easier to write good designs, and
harder to write questionable ones. There's a lot of rules in D that are
like that, just the whole notion of marking shared data is one of them.
I want to stress that this idea of preventing member variables from being
marked shared is not necessarily a *requirement*, it's merely something I
think fosters good design. There's nothing technically wrong with it, I
just think code is better off not doing it.
But marking stack variables as shared I think has to go -- there are too
many pitfalls, a cast should be required.
>>>> I think a better way to mark progress is to make it an atomic integer
>>>> type (like Artur has developed).
>>>
>>> Yes. The problem with that however is that I never managed to make this
>>> do the right thing:
>>>
>>> Atomic!int a; // somewhere in a shared struct/class.
>>> ...
>>> int x = s.a; // OK, access via getter.
>>> auto y = s.a; // Oops, we just copied the whole struct.
>>> void f(T)(T arg);
>>> f(s.a); // Ditto.
>>>
>>> Which may happen to work for properly aligned small structs because
>>> accessing those are atomic anyway, but is wrong.
>>
>> You can disable copying with @disable this(this);
>
> I wish.
>
> shared struct S { int x; @disable this(this); }
> shared S s;
> Error: cannot implicitly convert expression (this) of type shared(S) to S
This *definitely* is a bug.
>
> The post-dec/inc rewriting together with this bug also means you cannot
> prevent the bogus atomic++ operation from succeeding.
>
> And that is not the only problem with 'shared' and structs.
>
> http://www.digitalmars.com/d/archives/digitalmars/D/Disabling_copy_constructor_in_shared_structs_157638.html
> http://www.digitalmars.com/d/archives/digitalmars/D/dtors_in_shared_structs_fail_to_compile_157978.html
Haven't read these, but if there are bugs in the compiler, make sure you
file those. @disable this(this) *should* work, if it doesn't its a bug.
-Steve
More information about the Digitalmars-d
mailing list