www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DIP74 updated with new protocol for function calls

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Defines a significantly better function call protocol:

http://wiki.dlang.org/DIP74

Andrei
Feb 28 2015
next sibling parent reply "Zach the Mystic" <reachzach gggmail.com> writes:
On Saturday, 28 February 2015 at 21:12:54 UTC, Andrei 
Alexandrescu wrote:
 Defines a significantly better function call protocol:

 http://wiki.dlang.org/DIP74

 Andrei
This is obviously much better, Andrei. I think an alternative solution (I know -- another idea -- against my own first idea!) is to keep track of this from the caller's side. The compiler, in this case, when copying a ref-counted type (or derivative) into a parameter, would actually check to see if it's splitting the variable in two. Look at this: class RcType {...} void fun(RcType1 c, RcType1 d); auto x = new RcType; fun(x, x); If the compiler were smart, it would realize that by splitting parameters this way, it's actually adding an additional reference to x. The function should get one x for free, and then force an opAdd/opRelease, for every additional x (or x derivative) it detects in the same call. This might be even better than the improved current proposal. The real key is realizing that duplicating an lvalue into the same function call is subtly adding a new reference to it. Eh??
Feb 28 2015
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/28/15 11:04 PM, Zach the Mystic wrote:
 keep track of this from the caller's side.
Thanks, I'll keep that in mind. -- Andrei
Feb 28 2015
prev sibling next sibling parent reply "Matthias Bentrup" <matthias.bentrup googlemail.com> writes:
On Sunday, 1 March 2015 at 07:04:09 UTC, Zach the Mystic wrote:
 On Saturday, 28 February 2015 at 21:12:54 UTC, Andrei 
 Alexandrescu wrote:
 Defines a significantly better function call protocol:

 http://wiki.dlang.org/DIP74

 Andrei
This is obviously much better, Andrei. I think an alternative solution (I know -- another idea -- against my own first idea!) is to keep track of this from the caller's side. The compiler, in this case, when copying a ref-counted type (or derivative) into a parameter, would actually check to see if it's splitting the variable in two. Look at this: class RcType {...} void fun(RcType1 c, RcType1 d); auto x = new RcType; fun(x, x); If the compiler were smart, it would realize that by splitting parameters this way, it's actually adding an additional reference to x. The function should get one x for free, and then force an opAdd/opRelease, for every additional x (or x derivative) it detects in the same call. This might be even better than the improved current proposal. The real key is realizing that duplicating an lvalue into the same function call is subtly adding a new reference to it. Eh??
Note that you can get the same issue without duplicate parameters, if you pass an alias to a global variable. static A a; void fun(A x) { a = null; // Releases x x.func(); } void main() { a = new A(); fun(a); }
Mar 01 2015
next sibling parent "Zach the Mystic" <reachzach gggmail.com> writes:
On Sunday, 1 March 2015 at 08:57:17 UTC, Matthias Bentrup wrote:
 Note that you can get the same issue without duplicate 
 parameters, if you pass an alias to a global variable.

 static A a;

 void fun(A x) {
   a = null; // Releases x
   x.func();
 }

 void main() {
   a = new A();
   fun(a);
 }
Well don't do that... :-) Looks like a fly in the ointment. The most straightforward solution is to always add the opAdd/Release cycle when passing globals to impures. That's probably good enough. You probably don't pass a global to an impure very often anyway.
Mar 01 2015
prev sibling parent Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 1 March 2015 at 18:57, Matthias Bentrup via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Sunday, 1 March 2015 at 07:04:09 UTC, Zach the Mystic wrote:
 On Saturday, 28 February 2015 at 21:12:54 UTC, Andrei Alexandrescu wrote:
 Defines a significantly better function call protocol:

 http://wiki.dlang.org/DIP74

 Andrei
This is obviously much better, Andrei. I think an alternative solution (I know -- another idea -- against my own first idea!) is to keep track of this from the caller's side. The compiler, in this case, when copying a ref-counted type (or derivative) into a parameter, would actually check to see if it's splitting the variable in two. Look at this: class RcType {...} void fun(RcType1 c, RcType1 d); auto x = new RcType; fun(x, x); If the compiler were smart, it would realize that by splitting parameters this way, it's actually adding an additional reference to x. The function should get one x for free, and then force an opAdd/opRelease, for every additional x (or x derivative) it detects in the same call. This might be even better than the improved current proposal. The real key is realizing that duplicating an lvalue into the same function call is subtly adding a new reference to it. Eh??
Note that you can get the same issue without duplicate parameters, if you pass an alias to a global variable. static A a; void fun(A x) { a = null; // Releases x x.func(); } void main() { a = new A(); fun(a); }
Thing here is that 'a' does not belong to main(). There must be a reference on the caller's stack for it to be passed to a non-pure function. If a function X passes a value it does not own to some other function, then X needs to increment the refcount such that it holds one reference for itself. For the callee, it received via an argument, so it has confidence a stack reference exists, and it doesn't need to bump anymore down the call tree.
Mar 02 2015
prev sibling parent "Zach the Mystic" <reachzach gggmail.com> writes:
On Sunday, 1 March 2015 at 07:04:09 UTC, Zach the Mystic wrote:
 class RcType {...}

 void fun(RcType1 c, RcType1 d);

 auto x = new RcType;

 fun(x, x);

 If the compiler were smart, it would realize that by splitting 
 parameters this way, it's actually adding an additional 
 reference to x. The function should get one x for free, and 
 then force an opAdd/opRelease, for every additional x (or x 
 derivative) it detects in the same call.
One more tidbit: class RcType { RcType r; ... } void fun(RcType x, RcType y); auto z = new RcType; z.r = new RcType; fun(z, z.r); From within fun(), z can alias z.r, but z.r can't possibly alias z. Thus, only z.r needs to be preserved. The algorithm should go "For each parameter, add one ref/release cycle for every other parameter which could possibly generate an alias to it". We're approaching optimal here. This is feeling good to me.
Mar 01 2015
prev sibling next sibling parent reply "Paulo Pinto" <pjmlp progtools.org> writes:
On Saturday, 28 February 2015 at 21:12:54 UTC, Andrei 
Alexandrescu wrote:
 Defines a significantly better function call protocol:

 http://wiki.dlang.org/DIP74

 Andrei
What about having an UDA or a mixin for marking the types as RCO? -- Paulo
Mar 01 2015
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/1/15 1:41 AM, Paulo Pinto wrote:
 On Saturday, 28 February 2015 at 21:12:54 UTC, Andrei Alexandrescu wrote:
 Defines a significantly better function call protocol:

 http://wiki.dlang.org/DIP74

 Andrei
What about having an UDA or a mixin for marking the types as RCO?
We prefer opAddRef/opRelease to define an RCO, same as empty/front/popFront define a range. -- Andrei
Mar 01 2015
parent Jacob Carlborg <doob me.com> writes:
On 2015-03-01 13:41, Andrei Alexandrescu wrote:

 We prefer opAddRef/opRelease to define an RCO, same as
 empty/front/popFront define a range. -- Andrei
I don't see how a UDA would hurt. -- /Jacob Carlborg
Mar 01 2015
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2015-03-01 10:41, Paulo Pinto wrote:

 What about having an UDA or a mixin for marking the types as RCO?
I already commented on that. Andrei said [1] he was fine with breaking code for this feature. I don't understand why because it so easy to fix with a compiler recognized UDA [2]. [1] http://forum.dlang.org/post/mcqik9$5fu$1 digitalmars.com [2] http://forum.dlang.org/post/mcp5nu$1nus$1 digitalmars.com -- /Jacob Carlborg
Mar 01 2015
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Jacob Carlborg"  wrote in message news:mcv342$2c9t$1 digitalmars.com...

 I already commented on that. Andrei said [1] he was fine with breaking 
 code for this feature. I don't understand why because it so easy to fix 
 with a compiler recognized UDA [2].
Because a compiler recognized UDA is an additional complication for something that is unlikely to be a problem for anyone. Do you have code with methods named opAddRef? No? Me neither.
Mar 01 2015
next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Mon, 02 Mar 2015 00:15:02 +1100, Daniel Murphy wrote:

 "Jacob Carlborg"  wrote in message news:mcv342$2c9t$1 digitalmars.com...
=20
 I already commented on that. Andrei said [1] he was fine with breaking
 code for this feature. I don't understand why because it so easy to fix
 with a compiler recognized UDA [2].
=20 Because a compiler recognized UDA is an additional complication for something that is unlikely to be a problem for anyone. Do you have code with methods named opAddRef? No? Me neither.
so i should buy a reddit account with good reputation to change that, as=20 we all know that only reddit users matters.=
Mar 01 2015
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2015-03-01 14:15, Daniel Murphy wrote:

 Because a compiler recognized UDA is an additional complication for
 something that is unlikely to be a problem for anyone.  Do you have code
 with methods named opAddRef?  No?  Me neither.
I don't agree. If those are the final names, no. But I do have method names like "retain" and "release". I don't really like how it's done with ranges either. -- /Jacob Carlborg
Mar 02 2015
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2015-02-28 22:12, Andrei Alexandrescu wrote:
 Defines a significantly better function call protocol:

 http://wiki.dlang.org/DIP74
Is there any checking that the signatures of these methods matches the ones in the base class if an implicit conversion to the base class is made? Example: class Base { void opAddRef(); void opRelease(); } class Sub : Base { int opAddRef(); int opRelease(); } Base b = new Sub; // what happens here? On all examples showing how the compiler will insert calls to "opAddRef" and "opRelease" the return value is ignored. Is there a point in returning anything form these methods? -- /Jacob Carlborg
Mar 01 2015