[dmd-concurrency] Defining shared delegates

Steve Schveighoffer schveiguy at yahoo.com
Tue Jan 19 11:43:32 PST 2010





----- Original Message ----
> From: Michel Fortin <michel.fortin at michelf.com>
> To: Discuss the concurrency model(s) for D <dmd-concurrency at puremagic.com>
> Sent: Tue, January 19, 2010 2:27:28 PM
> Subject: [dmd-concurrency] Defining shared delegates
> 
> I think we should define a shared delegate as a delegate you can pass to other 
> threads, and which other threads can call.
> 
> The delegate contains a data pointer and a function pointer. The function's code 
> is always immutable so there is never a problem sharing it. The data it carries 
> can be part thread-local, part shared, part immutable. So here are the proposed 
> rules:
> 
> - If the data carried by the delegate is thread-local, in whole or in part, 
>   then the delegate is thread-local.
> - If the data is all shared or immutable, then the delegate can be shared.
> 
> I believe all delegates should be shared when they refer only to immutable and 
> shared data, and a shared delegate should implicitly convert to a thread-local 
> delegate when necessary.
> 
> Does it make sense that shared delegates convert implicitly to thread-local 
> ones? This might look a little suspicious at first because you can't do that 
> with other types, but with a delegate the data is private to only the associated 
> code, and the associated code already knows whether the data is really shared or 
> not, it is not relying on the caller's knowledge to call the right function like 
> elsewhere. The result is that we can safely discard shared from the type the 
> caller sees as it has no consequence.
> 
> So this should be an error (and already is) because the delegate is accessing 
> thread-local, mutable variables a and b:
> 
>     alias shared int delegate() SampleSharedDelegate;
> 
>     SampleSharedDelegate func1() {
>         int a, b;
>         return { return a + b; }; // error: cannot make delegate shared
>     }
> 
> This should work since a and b are shared:
> 
>     SampleSharedDelegate func2() {
>         shared int a, b;
>         return { return a + b; }; // ok, delegate can be shared
>     }
> 
> This too should work because a and b are immutable:
> 
>     SampleSharedDelegate func3() {
>         immutable int a, b;
>         return { return a + b; }; // ok, delegate can be shared
>     }
> 
> Does all this makes sense?

What about this?

SampleSharedDelegate func4() {
   int x, y;
   immutable int a, b;
   return { return a + b; };
}

The stack frame contains both thread-local and immutable variables, but the delegate only accesses the immutable ones.  Should this be allowed?  A more explicit case:

class X
{
   shared int a, b;
   int x, y;

   int foo() { return a + b; }
}

should foo be allowed to be a shared delegate?  What if the compiler only can see the signature?

I think shared delegates should only be callable on shared classes/structs, or else you should have to mark the inner function shared:

SampleSharedDelegate func4()
{
  shared int a, b;
  int x, y;

  shared int foo() { return a + b; }
  //shared int foo2() { return x + y; } // fails to compile, shared inner function using unshared members of the stack frame.
  int foo3() { return x + y; }
  return &foo; // ok
  return &foo3; // not ok, it was not marked as shared.
}

-Steve



      


More information about the dmd-concurrency mailing list