On Mon, 11 Jun 2012 09:39:40 -0400, Artur Skawina <[email protected]> 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

Reply via email to