D2 Multithreading Architecture

Robert Jacques sandford at jhu.edu
Thu Apr 30 07:58:15 PDT 2009


On Thu, 30 Apr 2009 07:04:59 -0400, Michel Fortin  
<michel.fortin at michelf.com> wrote:
> On 2009-04-29 22:54:20 -0400, "Robert Jacques" <sandford at jhu.edu> said:
>
>> On Wed, 29 Apr 2009 21:25:32 -0400, Michel Fortin   
>> <michel.fortin at michelf.com> wrote:
>>
>>> That's basically why I suggested adding scope constrains back then. To  
>>> implement swap safely, you need to know that the scope of the pointer  
>>> you are assigning to is always smaller or equal to the scope of the  
>>> memory block you're feeding them with.
>>>  Here's a new syntax for expressing contrains I've been thinking about:
>>>  	void swap(scope int* x, scope int* y)
>>> 	  scope(x = y && y = x)  // caller enforces that y is assignable to x  
>>> and x to y
>>> 	{
>>> 		scope(x = t && t = y) int* t;
>>> 		// y assignable to t and t to x; also imply that
>>> 		// x is assignable to y, which holds against previous constrains
>>>  		t = y;  // valid since scope(t = y)
>>> 		y = x;  // valid since scope(y = x)
>>> 		x = t;  // valid since scope(x = t)
>>> 	}
>>>  Perhaps with simple escape analysis, the compiler could infer the  
>>> scope constrains of local variable t so you don't have to write it  
>>> everywhere.
>>  You know, the implementation of swap is really a bad example, since  
>> using  a template works fine:
>> void swap(T)(ref T x, ref T y) {
>>      T t
>>      t = y;
>>      y = x;
>>      x = t;
>> }
>
> You know, all functions could be made templates and it'd solve all our  
> problems. Why aren't we doing that?
>
> Seriously, templates can't be the answer to everything. What if you  
> wanted swap as a member function of a class, and want to override it in  
> a derived class? We need a system that works with non-templates too.

I agree, which is why using a function where people immediately think  
'shouldn't that be a template' is a bad example.
By the way, using
scope(x = t && t = y) int* t;
implies to me that the function is templated.

>> Object a;
>> Object b;
>> shared Object c;
>> swap(a,b);   // Okay
>> swap(b,c);   // Error, template instantiation swap(local object, shared  
>>  object)
>
> In the case of my function with constrains you'd get something alike:
>
> 	swap(b,c); // Error, 'swap' wants c (shared Object c)
> 	// to be assignable to b (local Object b) which isn't allowed.
>
> Basically, you can't copy a scope variable to another scope variable  
> inside a function (because they may not be of the same scope and/or  
> ownership) unless the signature includes a constrain signaling the  
> assignement, which is then evaluated at the call site.

Agreed

>> Here are some specific issues:
>> 1) You seem to assume that different ownerships are interchangable.  
>> They  are not. Even if the data layout and member signatures are the  
>> made to be  the same, shared objects must maintain sequential  
>> consistency (i.e. memory  fences).
>> 1a) Limiting object signatures to being identical makes it hard for   
>> library writers to make a class that can be both allocated on both the   
>> shared and local heaps.
>
> Where am I assuming that? How?

Sorry. I was making assumptions based on your previous proposal of scope  
constraints:

void swap(scope ref int* a, scope ref int* b)
     if ((*a).scope <= b.scope && (*b).scope <= a.scope)

The <= operator implies that it is possible that an object of one  
ownership might get assigned to an object of a different ownership.

I was also making the assumption that the scope function parameter implied  
templating on that ownership type, as implied by.
scope(x = t && t = y) int* t;

Speaking of limiting constraints to equality, how about:

void swap(scope[0] ref int* x, scope[0] ref int* y) {
     scope[0] t;
     t = x;
     x = y;
     y = t;
}

with scope meaning any owner and scope[id] meaning the same ownertype as  
all the other scope[id]'s. (id is a number or identifier)

Hmm... scope[>id] and scope[<id] also seem intuitive.

An advantage I see with this approach is that swap composes much more  
easily:

void bar(scope ref int* x, scope ref int* y)
     scope(x = y && y = x)   // Possible information loss, compiler knows  
satisfaction, not what generated satisfaction
{
     swap(x,y);              // Does the compiler know enough to allow this  
call?
}

void bar(scope[0] ref int* x, scope[0] ref int* y) {
     swap(x,y); // Yes, the compiler knows x and y have the same scope
}

> Perhaps I'm not understanding something of your proposal, but I don't  
> see how adding scope constrains breaks shared objects.

Adding any scope restraints other than equality, can be shared objects.  
See above.
Perhaps this will explain my thinking better:

shared class Foo {}

becomes

Interface __scope_Foo {}
class __local_foo:  __scope_Foo {}
class __shared_foo: __scope_Foo {}

under the hood. Even if scope is a super-type and not an interface, you  
can see how these two ownerships might produce incompatible classes. Of  
importance is that member variables are sequentially consistent on shared  
types vs non-shared types and that they may have different vtables, etc.

> You say you want "scope" to be the super-type of all, which means that  
> it should accept both local and shared variables, am I right? If that's  
> the case I was right to write variable as being scope in my swap  
> function, so it can accept everything.

No, I said that scope is the super-interface of all. Which would have made  
a difference if you were using objects instead of int*s.

>> 2) You shouldn't rely on escape analysis to determine your function   
>> signature. It essentially forces you to do whole program static escape   
>> analysis, if you want to do it right, which is implausible. Consider   
>> recursive and member functions. What's the proper signature? And this   
>> isn't even considering the composability and forward referencing issues.
>
> That I certainly agree with. (And I never suggested escape analysis to  
> determine the scope of function arguments, only local variables inside  
> the function.)

Opps, I misread that.





More information about the Digitalmars-d mailing list