Possible to pass a member function to spawn?

Artur Skawina art.08.09 at gmail.com
Wed Feb 8 13:26:57 PST 2012


On 02/08/12 19:51, Timon Gehr wrote:
> On 02/08/2012 07:30 PM, Artur Skawina wrote:
>> On 02/08/12 18:24, Timon Gehr wrote:
>>>
>>> Open issue:
>>>
>>> void main(){
>>>      unique x = new C;
>>>      pragma(msg, typeof(x.z)); // ???
>>>      auto y = x.z; // error?
>>>      immutable z = x;
>>> }
>>>
>>> x.z is not necessarily unique, but assigning it to y breaks the guarantees of the unique qualifier of x.
>>
>> This is why treating "unique" as a static storage class doesn't really work. One
>> of the two last lines above would have to be disallowed,
> 
> 
> Actually that is not true. It could type check, because y is not alive after x has been cast to immutable.

I assumed this was a simplified example and both 'y' and 'z' would be accessed later.

> The problem shows here:
> 
> void main(){
>     unique x = new C;
>     auto y = x.z;
>     immutable z = x;
>     foo(y,z);
> }

But in real code the situation will be more complex, and like i said, while i
think it can be done in theory, i don't think it should. Consider your two above
examples - you want to allow something that's not really useful (dead assignment,
that will be eliminated by an optimizing compiler), while not really solving
the real case (for which there's no ideal solution, if it were to be legal).

>> and that reduces its usefulness dramatically.
> 
> Can you show me an example of its use?

I think that introducing a new type modifier/class might not be necessary. What if
in all these examples we were to use "auto" instead of "unique" when declaring the
variables _and_ have the compiler internally keep a 'unique' flag? It can then do
the safe conversions implicitly, and this is still backwards compatible. The
problematic cases are a) accessing the type directly (ie typeof etc) and b) multiple
conflicting assignments.

Also, consider your original example from this thread:

> void main(){
>     auto x = new C; // pure or scope
>     auto y = x;
>     y.foo(); // pure or scope
>     spawn(&bar, x); // fine!
> } 

What if 'x' is used after the call to spawn()? If we effectively passed
ownership of our unique instance to another context, 'x' can no longer
be "unique". If it were to mutate to the target type, then leaving it
accessible from the current context should be reasonably safe.

(Unless the new type is "unique" too - but allowing this only when there
are no further accesses to 'x' should be enough) 


>> The "auto" assignment either has to be illegal, or
>> trigger a mutation, eg to immutable. I don't think having the compiler keep
>> track of all possible relations would be a practical solution, even if theoretically
>> possible.
> 
> I think it would be practical enough.
> 
> typeof(C.z) global;
> 
> void main(){
>     unique x = new C;
>     auto y = x.z;
>     static assert(!is(typeof(y)==immutable));
>     static assert(!is(typeof({global = y;}));
>     immutable z = x;
>     static assert(is(typeof(y)==immutable));
>     static assert(is(typeof(x)==immutable);
>     foo(y,z);
> }

'y's type changed here - this wouldn't have worked for a "static" unique type.
And if it can work for "auto" - is an explicit "unique" for 'x' needed?
This example *could* work, but the interesting cases are the ones when the
assignments/mutations are non-trivial and done because the data is actually
used - i'm worried that doing the analysis *then* would be too expensive.

artur


More information about the Digitalmars-d mailing list