On 11/13/2012 3:18 AM, Sönke Ludwig wrote:
Am 13.11.2012 12:00, schrieb Walter Bright:
By operating on the expression, a lot more cases can be handled.
Yes, but _only_ doing that, the unique property is lost as soon as the 
expression crosses the
statement border - then the type system somehow needs to take over.

That's where Unique!T comes in.


That is, except for shared data. Allowing shared data
greatly improves its flexibility for passing data between threads.

But because it guarantees that the type cannot contain non-unique data, it can 
allow multiple
dereferences and still guarantee that no references are shared. Only immutable 
(or shared)
references can be extracted. Everything else can only be copied or moved, 
keeping everything
isolated.

Allowing shared access into the middle of something means that unique pointers 
cannot be implicitly
cast to immutable.

Not to immutable, but it may still be moved to another thread without 
copying/locking etc. Since
this can be easily checked at compile time, in my current implementation, the 
freeze() method of
Isolated!T is only available if T is strongly isolated (i.e. does not contain 
shared references).

Ok.

The other trouble is doing assignments into the isolated data. What if you're 
assigning to a
pointer, and the pointer value is pointing outside of the isolated graph?


The trick is that an Isolated!T value only has references to immutable or other 
Isolated!U data. So
assigning to any field will never violate the isolation. Assigning to an 
Isolated!U field requires a
move().

Ok.

The result is, I think, more usable because a) shared data is allowed and b) 
step-by-step
construction of unique data is possible naturally without constantly moving a 
unique pointer around.
What makes the C# system usable are mostly the automatic uniqueness-recovery 
rules, and I think
those can only be implemented by the compiler (setting apart AST macros ;) ).

I think we can do this with __unique(Expression), which is not a pervasive 
change to the compiler,
it's fairly isoloated (!). That construct would perform the "recovery". I 
implemented a little bit
of this in NewExp::implicitConvTo().


But how can it do recovery across a statement boundary?

Assign to a Unique!T variable, then use that Unique!T variable in the next statement.

Anyways, it was partly a moot point on my part, as the Isolated struct can 
simply make sure to
expose only fields that are safe (i.e. POD, immutable or Isolated fields). 
Those can be freely
changed without violating isolation and thus no explicit recovery is even 
necessary. But other
fields with references to mutable or shared data are still difficult to handle.


Reply via email to