November 14, 2012
On 11/13/2012 3:47 PM, Daniel Murphy wrote:
> "Walter Bright" <newshound2@digitalmars.com> wrote in message
> news:k7t125$7on$1@digitalmars.com...
>>
>> A Unique!T can only be initialized by:
>>
>>     1. a destructive read of another instance of Unique!T
>>     2. an expression that can be determined to generated an isolated
>> pointer
>>
>> #2 is the interesting bit. That requires some compiler support, sort of
>> like:
>>
>>       __unique(Expression)
>>
>> which will allow it through if Expression is some combination of new, pure
>> functions, and other Unique pointers.
>>
>
> This is somewhat possible in the current language.  The makeU function can
> be an arbitrarily complicated strongly pure function.
>
> void funcTakingUnique(U, T...)(U function(T) pure makeU, T args) if
> (is(typeof({ immutable i = makeU(args) }) // If it converts to immutable, it
> is either unique or immutable
> {
>      auto unique = makeU(args); // guaranteed to be unique/immutable
> }
>
> class A
> {
>      this(int a, string b) {}
> }
>
> void main()
> {
>      funcTakingUnique!A(A function(int a, string b) { return new A(a, b); },
> 4, "Awesome");
> }
>
>

This is a great insight.
November 14, 2012
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.


November 14, 2012
On 11/14/2012 12:03 PM, Walter Bright wrote:
> ...
>>
>> 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.
>

What he meant is how to create temporary pointers to the data and then get an isolated reference to it again in a safe way.

1 2 3 4
Next ›   Last »