Immutable and unique in C#

Sönke Ludwig sludwig at outerproduct.org
Tue Nov 13 03:18:11 PST 2012


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. But extending its capabilities
using this is certainly a win.

> 
>> 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).

> 
> 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().

> 
>> 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?

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.



More information about the Digitalmars-d mailing list