[dmd-concurrency] is shared going to be a type modifier?

Steve Schveighoffer schveiguy at yahoo.com
Thu Jan 7 13:57:50 PST 2010


----- Original Message ----

> From: Sean Kelly <sean at invisibleduck.org>
> 
> On Jan 7, 2010, at 12:34 PM, Steve Schveighoffer wrote:
> 
> > ----- Original Message ----
> > 
> >> From: Andrei Alexandrescu 
> >> Steve Schveighoffer wrote:
> >>> Despite that, I think I get it.  The address to a shared member could
> >>> be passed to other threads, even though the full object is not, is
> >>> that correct?
> >> 
> >> Of course, plus the more frequent case is:
> >> 
> >> class SList { ... }
> >> struct A { int x; shared SList lst; }
> > 
> > This to me is a more normal usage.  The data that is shared is really the 
> list, not the pointer to the list (but the reference is also shared because of 
> the deficiencies of the type syntax).
> 
> Won't we be able to do:
> 
>     struct A { int x; shared(SList) lst; }

currently, const(T) applies to *all* of T, even the reference itself.  There is no syntax to apply const only to what T references if T is a class.  There was a huge discussion about this in the early days of the current const system.

There is a type called Rebindable(T) in std.typecons which essentially is equivalent to only applying const or immutable to the referenced item.  Although last I remember there were some problems with it because it used opDot.

> I'd think it would be pretty common to want a local reference to shared data.  
> Then you wouldn't have to pay for the atomic read required if the reference 
> itself is shared.

I think more than const, we need something like this for shared.

> 
> > To be more specific, the following case is odd to me because you are sharing 
> data in the same memory segment as unshared data:
> > 
> > struct B
> > {
> >   int x;
> >   shared int y;
> > }
> > 
> > And in fact, declaring a variable of type B in a function puts shared data on 
> the stack!
> 
> Yeah, a fully shared field inside a non-shared class doesn't sound right.  The 
> smoke test for me is that I think about whether it would work with per-thread 
> GCs.  If one thread has a reference to "shared" data that actually lives in 
> another thread's heap or stack, there's a dangling reference issue if the thread 
> terminates (at least in theory--the heap data could easily be handed off to the 
> shared GC instead, but let's pretend this is impossible).

Yeah, allowing this seems to imply that the global heap will have to be scanned for local heap collections:

class C
{
   shared(int)* ptr1;
   int *ptr2;
}

I assume that marking a single member shared makes C get allocated on the global heap.

If ptr1 points to a global-heap variable, and ptr2 points to a thread-local-heap variable, then you have to scan the global heap in order to collect the memory ptr2 is pointing to.

> > Hm... this brings up an interesting point.  If you want to say that a 
> reference to a shared class is a thread-local, how do you do that?  For 
> instance, in your struct A, you are most likely not going to share the actual 
> reference lst (i.e. &a.lst), just what lst points to.  However, the compiler is 
> going to assume you are sharing lst because that's what you declared.  So every 
> access to lst is going to require special memory barriers (and technically 
> wasted cycles).  Is there going to be a way around this?  With const it was not 
> as important because const is a compile-time concept, but now the syntax 
> deficiency is creeping into runtime and hurting performance.  I.e. are we going 
> to get an equivalent "Rebindable" type constructor?
> 
> See my example of "shared (Something) p" above.  This is consistent with how 
> const and such work anyway.

No it is not.  If you have const(T) x, you can never rebind x, no matter what type is inside the parens.

-Steve



      


More information about the dmd-concurrency mailing list