March 01, 2015
On 2/28/15 7:01 PM, Manu via Digitalmars-d wrote:
> On 1 March 2015 at 12:51, Andrei Alexandrescu via Digitalmars-d
> <digitalmars-d@puremagic.com> wrote:
>> On 2/28/15 6:49 PM, Manu via Digitalmars-d wrote:
>>>
>>> On 1 March 2015 at 12:21, Andrei Alexandrescu via Digitalmars-d
>>> <digitalmars-d@puremagic.com> wrote:
>>>>
>>>> On 2/28/15 5:43 PM, Manu via Digitalmars-d wrote:
>>>>>
>>>>>
>>>>> I'd like to see a struct with RC operators have implicit calls
>>>>> generated (and elided) for exactly the same set of cases as classes,
>>>>> in terms of construction/destruction/assignment/passing to/from
>>>>> functions.
>>>>
>>>>
>>>>
>>>> The short answer is that probably won't happen. -- Andrei
>>>
>>>
>>> *sigh* ... ever, or in DIP74?
>>
>>
>> In the foreseeable future.
>>
>>> I presented my 80% case to you before. I just want this to work
>>> efficiently:
>>>
>>> extern(C) void inc(void*);
>>> extern(C) void dec(void*);
>>>
>>> struct X
>>> {
>>>     void *thing;
>>>
>>>     opInc() { inc(thing); }
>>>     opDec() { dec(thing); }
>>> }
>>
>>
>> struct X
>> {
>>    void *thing;
>>
>>    this(this) { inc(thing); }
>>    ~this() { dec(thing); }
>> }
>
> You've conveniently ignored the word 'efficient'.

Inserting calls to opAddRef and opRelease, and the rules that allow their elision, follow quite closely (albeit not 100% identically) the rules for inserting calls to copy constructors and destructors.

> Okay, so if I'm not better off then I've always been, what is the good
> of DIP74 to me?

The title reads "Reference Counted Class Objects".


Andrei

March 01, 2015
On 1 March 2015 at 13:13, Andrei Alexandrescu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On 2/28/15 7:01 PM, Manu via Digitalmars-d wrote:
>>
>> On 1 March 2015 at 12:51, Andrei Alexandrescu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>>
>>> On 2/28/15 6:49 PM, Manu via Digitalmars-d wrote:
>>>>
>>>>
>>>> On 1 March 2015 at 12:21, Andrei Alexandrescu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>>>>
>>>>>
>>>>> On 2/28/15 5:43 PM, Manu via Digitalmars-d wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> I'd like to see a struct with RC operators have implicit calls generated (and elided) for exactly the same set of cases as classes, in terms of construction/destruction/assignment/passing to/from functions.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> The short answer is that probably won't happen. -- Andrei
>>>>
>>>>
>>>>
>>>> *sigh* ... ever, or in DIP74?
>>>
>>>
>>>
>>> In the foreseeable future.
>>>
>>>> I presented my 80% case to you before. I just want this to work efficiently:
>>>>
>>>> extern(C) void inc(void*);
>>>> extern(C) void dec(void*);
>>>>
>>>> struct X
>>>> {
>>>>     void *thing;
>>>>
>>>>     opInc() { inc(thing); }
>>>>     opDec() { dec(thing); }
>>>> }
>>>
>>>
>>>
>>> struct X
>>> {
>>>    void *thing;
>>>
>>>    this(this) { inc(thing); }
>>>    ~this() { dec(thing); }
>>> }
>>
>>
>> You've conveniently ignored the word 'efficient'.
>
>
> Inserting calls to opAddRef and opRelease, and the rules that allow their elision, follow quite closely (albeit not 100% identically) the rules for inserting calls to copy constructors and destructors.

The most important case to be elided is the function call case.
Passing struct to function results in postblit and destructor for
every call.
If postblit and destructor were sufficient, we would have been
satisfied with RC in D for years.


>> Okay, so if I'm not better off then I've always been, what is the good of DIP74 to me?
>
>
> The title reads "Reference Counted Class Objects".

That title is not immutable.
If DIP74 is a starting point, and you can see extension to the struct
case in the future, then I'll let this go now.
March 01, 2015
On 2/26/2015 11:44 PM, anonymous wrote:
> We all pray you become less of a [...]

cut it out.

March 01, 2015
On 2/28/15 7:30 PM, Manu via Digitalmars-d wrote:
> On 1 March 2015 at 13:13, Andrei Alexandrescu via Digitalmars-d
> <digitalmars-d@puremagic.com> wrote:
>> Inserting calls to opAddRef and opRelease, and the rules that allow their
>> elision, follow quite closely (albeit not 100% identically) the rules for
>> inserting calls to copy constructors and destructors.
>
> The most important case to be elided is the function call case.
> Passing struct to function results in postblit and destructor for
> every call.
> If postblit and destructor were sufficient, we would have been
> satisfied with RC in D for years.

RefCounted has been in there for quite a while and worked with structs. Its main problem was it wasn't safe. With DIP25 safety of structs (including those that use reference counting for their payload) becomes a reality.

>>> Okay, so if I'm not better off then I've always been, what is the good
>>> of DIP74 to me?
>>
>>
>> The title reads "Reference Counted Class Objects".
>
> That title is not immutable.
> If DIP74 is a starting point, and you can see extension to the struct
> case in the future, then I'll let this go now.

It would be mightily confusing to add opAddRef and opRelease calls for structs that follow the constructors/destructors ever so closely. It might be more productive to look into improvements of optimizations related to copying objects.


Andrei

March 01, 2015
Jacob Carlborg:

> @arc class Foo
> {
>     T1 opAddRef();
>     T2 opRelease();
> }
> ...
> Alternative A gives a clear documentation it's a reference counted class without having to scan the methods.

Assuming you want something like DIP74, this design design seems safer than the design proposed in DIP74.

Bye,
bearophile
March 01, 2015
On Sunday, 1 March 2015 at 03:43:24 UTC, Andrei Alexandrescu wrote:
> It might be more productive to look into improvements of optimizations related to copying objects.
>
>
> Andrei

Yes please. I'd be very interested in hearing any thoughts you have on this.
March 01, 2015
On 3/1/15 6:55 AM, John Colvin wrote:
> On Sunday, 1 March 2015 at 03:43:24 UTC, Andrei Alexandrescu wrote:
>> It might be more productive to look into improvements of optimizations
>> related to copying objects.
>>
>>
>> Andrei
>
> Yes please. I'd be very interested in hearing any thoughts you have on
> this.

One that comes to mind is: if (a) a copy b of a struct object a is created, (b) b is used only with non-mutating operations, and (c) a is not changed before b goes out of scope, then a can be directly substituted for b (no actual copy is made).

Example:

struct S {
  this(this);
  ~this();
  int method() const;
}

int fun() {
  S a;
  S b = a;
  return b.method();
}

may be lowered to:

int fun() {
  S a;
  return a.method();
}


Andrei
March 02, 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

opAddRef/opRelease breaks SOLID's single responsibility principle.
March 03, 2015
On Sunday, 1 March 2015 at 13:13:58 UTC, bearophile wrote:
> Jacob Carlborg:
>
>> @arc class Foo
>> {
>>    T1 opAddRef();
>>    T2 opRelease();
>> }
>> ...
>> Alternative A gives a clear documentation it's a reference counted class without having to scan the methods.
>
> Assuming you want something like DIP74, this design design seems safer than the design proposed in DIP74.
>
> Bye,
> bearophile

So, I don't know a huge amount about this subject. aka. (hold my beer) but I do know that seemingly by default D has garbage collection which is wonderful... but It is also wonderful to have choices.

I see a story like the tortoise and the hare.  Where the garbage collector is like the hare, going really fast but then taking a break. Reference counting is like the tortoise, a bit slower but more predictable.

It is clear Reference counting takes more discipline, but unclear to me how D will help/guide its users through process. it seems like the @safe will disallow some obviously dumb things. which is actually really awesome.

It is also unclear how combining both RC and GC will work, how does the GC know not to scan the RC's territory?  And if it does is it actually beneficial to have RC?

As far as DIP74: In the Definition I am confused what UFCS has to do with defining the opAddRef() and opRelease() methods. And also why the are used in the fun() x.opAddref() example. I probably have like 100 more dumb questions but lets leave it there. :D
March 03, 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

With opAddRef/opRelease class does respondible for its dealocation and its own payload so breaks SOLID's single responsibility principle. As for me better design will be to do it closer to C++'s shared_ptr.
e.g:

// maybe with @arc
struct RefCounter(T)
{
void opAddRef();
void opRelease();
ref T obj;
ref size_t count;
}
}

RefCounter!Widged myRefToWidget;

RefCounter with default ctor/dtor. opAddRef and opRelease is for compiler optimtimisation and elimination of redunadant ref counter increment/decrement.