March 02, 2015
On Monday, 2 March 2015 at 20:36:53 UTC, Marc Schütz wrote:
> Interesting approach. I will have to think about that. But I think it does not really work. Your example hides the fact that there are actually two types involved (or can be): an RC wrapper, and the actual class. foo() would need to take at least `c1` as the wrapper type `RC!C`, not `C` itself, otherwise it couldn't copy it. But that defeats the purpose of borrowing, that it neutralizes the actual memory management strategy; foo() should know whether `c1` is reference counted or not.

Please reread. I'm assuming a refcounting system like Andrei's proposal for objects.

The result would be the same for a RefCounted wrapper (a solution that I would prefer) in the sense you'd have to copy the wrapper to get ownership of it before being able to assign to it.
March 02, 2015
On Monday, 2 March 2015 at 20:04:49 UTC, deadalnix wrote:
> I let the night go over that one. Here is what I think is the best road forward :
>  - triggering postblit and/or ref count bump/decrease is prohibited on borrowed.
>  - Acquiring and releasing ownership does.
>
> Now that we have this, let's get back to the exemple :
> class C {
>     C c;
>
>     // Make ti refconted somehow, doesn't matter. Andrei's proposal for instance.
> }
>
> void boom() {
>     C c = new C();
>     c.c = new C();
>
>     foo(c, c.c);
> }
>
> void foo(ref C c1, ref C c2) {
>     // Here is where things get different. c1 is borrowed, so you can't
>     // do c1.c = null before acquiring c1.c beforehand.

Right, I agree with this.

> That means the
>     // compiler needs to get a local copy of c1.c, bump the refcount
>     // to get ownership before executing c1.c = null and decrease
>     // the refcount.

Yeah, but should it do this inside foo() or in bump() right before it calls foo. I think in bump, and only for a parameter which might be aliased by another parameter (an extremely rare case). For any other case, the refcount has already been preserved:

void boom() {
    C c = new C(); // refcount(c) == 1
    c.c = new C(); // refcount(c.c) == 1
    auto d = c.c; // refcount(c.c) == 2 now
    foo(c, d); // safe
}

The only problem is the rare case when the exact same identifier is getting sent to two different parameters.

I'm sure there will be opportunities to elide a lot of refcount calls, but in this case,  I don't see much to left to elide.
March 02, 2015
You don't put the ownership acquire at the same place, but that is the same idea. It is probably even better to do it your way (or is it ?).
March 02, 2015
On Monday, 2 March 2015 at 22:00:56 UTC, deadalnix wrote:
> You don't put the ownership acquire at the same place, but that is the same idea. It is probably even better to do it your way (or is it ?).

Yes. Unless the compiler detects that you duplicate a variable in two parameters in the same call, you literally have *no* added cycles, anywhere:

fun(c, c.c);

This is the only time you pay any penalty (except for passing globals, as we now realize, since all globals can alias themselves as parameters -- nasty).
March 02, 2015
On Monday, 2 March 2015 at 22:21:11 UTC, Zach the Mystic wrote:
> On Monday, 2 March 2015 at 22:00:56 UTC, deadalnix wrote:
>> You don't put the ownership acquire at the same place, but that is the same idea. It is probably even better to do it your way (or is it ?).
>
> Yes. Unless the compiler detects that you duplicate a variable in two parameters in the same call, you literally have *no* added cycles, anywhere:
>
> fun(c, c.c);
>
> This is the only time you pay any penalty (except for passing globals, as we now realize, since all globals can alias themselves as parameters -- nasty).

Global simply are parameter implicitly passed to all function from a theoretical perspective. There are no reason to thread them differently.
March 02, 2015
On Monday, 2 March 2015 at 22:51:29 UTC, deadalnix wrote:
> On Monday, 2 March 2015 at 22:21:11 UTC, Zach the Mystic wrote:
>> On Monday, 2 March 2015 at 22:00:56 UTC, deadalnix wrote:
>>> You don't put the ownership acquire at the same place, but that is the same idea. It is probably even better to do it your way (or is it ?).
>>
>> Yes. Unless the compiler detects that you duplicate a variable in two parameters in the same call, you literally have *no* added cycles, anywhere:
>>
>> fun(c, c.c);
>>
>> This is the only time you pay any penalty (except for passing globals, as we now realize, since all globals can alias themselves as parameters -- nasty).
>
> Global simply are parameter implicitly passed to all function from a theoretical perspective. There are no reason to thread them differently.

Except for this:

static Rctype t; //

fun(t);

Now you have that implicit parameter which screws things up. It's like calling:

fun(@globals, t);

...where @globals is a namespace which can alias t. So you have two parameters which can alias each other. I think the only saving grace is that you probably don't really need to pass a global that often, since you already have it if you want it. Only if you want the global to "play the role" of a parameter.

What do you think? How many times do you normally pass a global?
March 03, 2015
On Monday, 2 March 2015 at 23:43:22 UTC, Zach the Mystic wrote:
> Except for this:
>
> static Rctype t; //
>
> fun(t);
>
> Now you have that implicit parameter which screws things up. It's like calling:
>
> fun(@globals, t);
>
> ...where @globals is a namespace which can alias t. So you have two parameters which can alias each other. I think the only saving grace is that you probably don't really need to pass a global that often, since you already have it if you want it. Only if you want the global to "play the role" of a parameter.
>
> What do you think? How many times do you normally pass a global?

I fail too see how t being global vs t being a local that is doubly passed change anything.
March 03, 2015
On Tuesday, 3 March 2015 at 00:02:48 UTC, deadalnix wrote:
>> What do you think? How many times do you normally pass a global?
>
> I fail too see how t being global vs t being a local that is doubly passed change anything.

Within the function, the global passed as a parameter creates an alias to the global. Fortunately, Andrei Fermat may have just solved the issue:

http://forum.dlang.org/post/md2pub$nqn$1@digitalmars.com
March 03, 2015
On Tuesday, 3 March 2015 at 00:11:36 UTC, Zach the Mystic wrote:
> On Tuesday, 3 March 2015 at 00:02:48 UTC, deadalnix wrote:
>>> What do you think? How many times do you normally pass a global?
>>
>> I fail too see how t being global vs t being a local that is doubly passed change anything.
>
> Within the function, the global passed as a parameter creates an alias to the global. Fortunately, Andrei Fermat may have just solved the issue:
>
> http://forum.dlang.org/post/md2pub$nqn$1@digitalmars.com

This does not solve anything as postblit only increase refcount so it does not make any sense that it deletes the payload.
March 03, 2015
On 3/2/15 4:35 PM, deadalnix wrote:
> On Tuesday, 3 March 2015 at 00:11:36 UTC, Zach the Mystic wrote:
>> On Tuesday, 3 March 2015 at 00:02:48 UTC, deadalnix wrote:
>>>> What do you think? How many times do you normally pass a global?
>>>
>>> I fail too see how t being global vs t being a local that is doubly
>>> passed change anything.
>>
>> Within the function, the global passed as a parameter creates an alias
>> to the global. Fortunately, Andrei Fermat may have just solved the issue:
>>
>> http://forum.dlang.org/post/md2pub$nqn$1@digitalmars.com
>
> This does not solve anything as postblit only increase refcount so it
> does not make any sense that it deletes the payload.

Yah, it's opAssign instead of postblit. -- Andrei