February 27, 2015
On 2/26/15 5:41 PM, weaselcat wrote:
> On Friday, 27 February 2015 at 00:10:00 UTC, deadalnix wrote:
>> No problem, I'm gonna duplicate all my code and as will every single
>> library writer out there.
>
> Correct me if I'm wrong, but to me this presents itself as an
> alternative only for things that require deterministic ownership
> semantics(e.g, OpenGL resource wrapper)
>
> I don't think this is a full ARC system intended to replace the GC that
> would require library authors to write two versions of their libraries.
>
> But I could be entirely wrong.

DIP74 allows defining objects outside the Object hierarchy that are reference counted. This allows apps in which GC and RC approaches coexist.

An interesting option to explore in the future would be rigging druntime to add opAddRef and opRelease to Object.


Andrei

February 27, 2015
On Thu, Feb 26, 2015 at 05:44:36PM -0800, Andrei Alexandrescu via Digitalmars-d wrote: [...]
> An interesting option to explore in the future would be rigging druntime to add opAddRef and opRelease to Object.
[...]

How would that work? Doesn't that immediately subject *all* classes to the restrictions set forth in DIP74?


T

-- 
Gone Chopin. Bach in a minuet.
February 27, 2015
On Thursday, 26 February 2015 at 21:50:56 UTC, Andrei Alexandrescu wrote:
> http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss.
>
> Thanks,
>
> Andrei

P.S., am I too late to complain about the choice of 'return' in DIP25? :)

If someone who learned C(++) but had used D read this

ref int opIndex(size_t n) return { // mark this as a non-escape reference
        return _payload[n];
}

I'm not sure if they could make heads or tails of what the first return is supposed to be doing.
February 27, 2015
On 2/26/15 5:43 PM, Andrei Alexandrescu wrote:
> The compiler will issue errors if returning ref to direct members. There
> won't be errors with returning ref to owned indirect members that the
> class deallocates manually. -- Andrei

To clarify this point, which I think is important, consider:

class Widget {
    private int x;
    private int[] a;
    ...
    ref int getX() { return x; }
    int[] getA() { return a; }
}

This is all fine and dandy - people can take and keep a reference to x in a GC object, and of course can get keep the array (or a portion of it) etc.

Now say we port Widget to an RC system:

class Widget {
    private int x;
    private int[] a;
    ...
    ref int getX() { return x; }
    int[] getA() { return a; }
    void opAddRef();
    void opRelease();
}

Not getX() does NOT compile anymore, whereas getA() CONTINUES to compile. To make getX() compile, the user must change code to:

    ref int getX() return { return x; }

That makes the compiler go, "oh ok I'll make sure the reference doesn't outlive the current object". And all is again fine and dandy.

Now if the person defining Widget wants to own (and release deterministically) the array, they must make sure their use of memory is scoped appropriately, e.g. by using RCSlice.


Andrei


February 27, 2015
On 2/26/15 5:59 PM, H. S. Teoh via Digitalmars-d wrote:
> On Thu, Feb 26, 2015 at 05:44:36PM -0800, Andrei Alexandrescu via Digitalmars-d wrote:
> [...]
>> An interesting option to explore in the future would be rigging
>> druntime to add opAddRef and opRelease to Object.
> [...]
>
> How would that work? Doesn't that immediately subject *all* classes to
> the restrictions set forth in DIP74?

It does - but that might be fine with some applications. -- Andrei

February 27, 2015
On Friday, 27 February 2015 at 02:05:12 UTC, weaselcat wrote:
> On Thursday, 26 February 2015 at 21:50:56 UTC, Andrei Alexandrescu wrote:
>> http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss.
>>
>> Thanks,
>>
>> Andrei
>
> P.S., am I too late to complain about the choice of 'return' in DIP25? :)
>
> If someone who learned C(++) but had used D read this
hadn't*, Sorry.
February 27, 2015
On Friday, 27 February 2015 at 02:05:33 UTC, Andrei Alexandrescu wrote:
> On 2/26/15 5:43 PM, Andrei Alexandrescu wrote:
>> The compiler will issue errors if returning ref to direct members. There
>> won't be errors with returning ref to owned indirect members that the
>> class deallocates manually. -- Andrei
>
> To clarify this point, which I think is important, consider:
>
> class Widget {
>     private int x;
>     private int[] a;
>     ...
>     ref int getX() { return x; }
>     int[] getA() { return a; }
> }
>
> This is all fine and dandy - people can take and keep a reference to x in a GC object, and of course can get keep the array (or a portion of it) etc.
>
> Now say we port Widget to an RC system:
>
> class Widget {
>     private int x;
>     private int[] a;
>     ...
>     ref int getX() { return x; }
>     int[] getA() { return a; }
>     void opAddRef();
>     void opRelease();
> }
>
> Not getX() does NOT compile anymore, whereas getA() CONTINUES to compile. To make getX() compile, the user must change code to:
>
>     ref int getX() return { return x; }
>
> That makes the compiler go, "oh ok I'll make sure the reference doesn't outlive the current object". And all is again fine and dandy.
>
> Now if the person defining Widget wants to own (and release deterministically) the array, they must make sure their use of memory is scoped appropriately, e.g. by using RCSlice.
>
>
> Andrei

It is the same with a pointer to a struct.
February 27, 2015
On Thu, Feb 26, 2015 at 06:06:04PM -0800, Andrei Alexandrescu via Digitalmars-d wrote:
> On 2/26/15 5:59 PM, H. S. Teoh via Digitalmars-d wrote:
> >On Thu, Feb 26, 2015 at 05:44:36PM -0800, Andrei Alexandrescu via Digitalmars-d wrote: [...]
> >>An interesting option to explore in the future would be rigging druntime to add opAddRef and opRelease to Object.
> >[...]
> >
> >How would that work? Doesn't that immediately subject *all* classes to the restrictions set forth in DIP74?
> 
> It does - but that might be fine with some applications. -- Andrei

But putting it into druntime imposes it on *all* applications, because either opAddRef/opRelease are declared in Object, or they are not, and this decision is made long before the user writes his application.


T

-- 
In theory, software is implemented according to the design that has been carefully worked out beforehand. In practice, design documents are written after the fact to describe the sorry mess that has gone on before.
February 27, 2015
On 2/26/15 6:21 PM, H. S. Teoh via Digitalmars-d wrote:
> On Thu, Feb 26, 2015 at 06:06:04PM -0800, Andrei Alexandrescu via Digitalmars-d wrote:
>> On 2/26/15 5:59 PM, H. S. Teoh via Digitalmars-d wrote:
>>> On Thu, Feb 26, 2015 at 05:44:36PM -0800, Andrei Alexandrescu via Digitalmars-d wrote:
>>> [...]
>>>> An interesting option to explore in the future would be rigging
>>>> druntime to add opAddRef and opRelease to Object.
>>> [...]
>>>
>>> How would that work? Doesn't that immediately subject *all* classes
>>> to the restrictions set forth in DIP74?
>>
>> It does - but that might be fine with some applications. -- Andrei
>
> But putting it into druntime imposes it on *all* applications, because
> either opAddRef/opRelease are declared in Object, or they are not, and
> this decision is made long before the user writes his application.

That's why I used "rigging" - meaning "equip for special purpose". "Hacking" is clearer. Someone may decide to just add opAddRef/opRelease to Object for a system or application. Or make the addition subject to a versioning flag (and therefore have two druntime builds available).

Andrei

February 27, 2015
On 2015-02-26 22:50, Andrei Alexandrescu wrote:
> http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and
> discuss.

* What will happen if these methods are defined on a class that is allocated on the GC? Is there any enforcement against this? Is there any way an unsafe operation can happen, i.e. the GC deleting a class that has already been destroyed by reference counting?

What about enforcing a third method, "allocate" or similar. This method will do the actually allocation of a class instance. "new Foo" could be lowered to a call to "allocate".

* I know this is bikeshedding but I think it's important. This is a breaking change, like it or not, and it's the worst kind. The kind that if a class exists with these methods it will continue to happily compile without errors or warnings but will have different semantic behavior. Therefore I recommend requiring a compiler recognized UDA, in one of the following ways:

A.

@arc class Foo
{
    T1 opAddRef();
    T2 opRelease();
}

If a class is marked with @arc the compiler will enforce that both "opAddRef" and "opRelease" are defined with the expected signatures.

B.

class Foo
{
    @arc T1 opAddRef();
    @arc T2 opRelease();
}

If either a method is called "opAddRef" or "opRelease" and it's marked with @arc, the compiler will enforce that the other method is defined and marked with @arc as well. The signatures of the methods are enforced as well.

C.

class Foo
{
    @arc("addRef") T1 foo();
    @arc("release") T2 bar();
}

Basically the same as B but the actual methods can be called anything.

Alternative A gives a clear documentation it's a reference counted class without having to scan the methods.

-- 
/Jacob Carlborg