February 27, 2015
On Friday, 27 February 2015 at 08:26:14 UTC, Ola Fosheim Grøstad wrote:
> On Thursday, 26 February 2015 at 22:04:09 UTC, Andrei Alexandrescu wrote:
>> On 2/26/15 2:03 PM, Brian Schott wrote:
>>>
>>> One of the first things that stood out to me is that "add ref" is two
>>> words and "release" is one. For the sake of symmetry, how about these:
>>> *  opIncRef, opDecRef
>>> *  opAcquire, opRelease
>>
>> All - please PLEASE do not derail this into yet another debate about which names are best. -- Andrei
>
> Using protocols rather than enforcing a particular implementation is nice, but D needs to stop reinventing terminology and syntax matters.
>
> -- snip --

AddRef/Release is established COM terminology.
February 27, 2015
On Friday, 27 February 2015 at 07:44:18 UTC, anonymous wrote:
> On Friday, 27 February 2015 at 00:10:00 UTC, deadalnix 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
>>
>> "The compiler detects automatically and treats specially all classes and interfaces that define the following two methods:"
>>
>> Well, RefCounted could use compile time reflexion to do so. Even better, we could define a lvalue property for RefCounted to use a counter so we can do intrusive counting in both classes and structs.
>>
>> "@safe code may not issue explicit calls to opAddRef/opRelease. "
>>
>> I guess we could simply make them @system .
>>
>> " RCOs objects are subject to additional limitations compared to their GC counterparts:
>>
>> No conversion to Object or interfaces that are not reference counted "
>>
>> No problem, I'm gonna duplicate all my code and as will every single library writer out there.
>>
>> Missing:
>>
>> All write of RCO reference to statics must be atomic and ordered as long as the language can't enforce thread locality (at least in @safe code).
>>
>> Generally:
>> This DIP works around (announced) limitations of DIP25. As escape can only be checked properly for type with no indirections, and only solve the problem for classes/interfaces. Other type with indirection remains an unsolved problem.
>>
>> If I were in charge, that would be a clear no, and the sign that DIP25 approach needs to be reworked, as wack-a-mole is not a good way to handle design.
>
> We all pray you become less of a gaping asshole before youre in
> charge of anything.

In fact, "we all" don't. Quite the opposite, several of the participants of these forums (me included) happen to agree with him on many things, not just this particular topic. That's because he brings forward good arguments for his opinions, which is evidently something you aren't capable of.
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

It's kind of funny that you were looking for an edge to my safety system -- I'll admit I don't know whether it really has an edge or not (it might be too bloated, both function-signature-wise and compile-time-wise) -- but one key advantage to any sophisticated ownership system is that automated reference counting can elide calls which it knows are unnecessary. What struck me in particular about DIP74 is how the pass-by-value protocol will force many function calls to endure an opAddRef/opRelease cycle, even if they do nothing to the reference count.

What really worries me is that if the caller is responsible for the opAddRef, while the callee is responsible for the opRelease, isn't the potential optimization of eliding them just being sacrificed?
February 27, 2015
On 2015-02-26 21:50:55 +0000, Andrei Alexandrescu said:

> http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss.

Looks good in general.

Somehow I can't help but think how overloading new and delete would be useful in combination with this. You know, this feature from D1 that was deprecated for some reason (but still work fine as far as I know)?
http://digitalmars.com/d/1.0/class.html#allocators

	class MyRCObject
	{
		new(size_t size) { return malloc(size); }
		delete(void* ptr) { free(ptr); }

		private size_t refs = 1;
		void opAddRef() { ++refs; }
		void opRelease() { if (--refs == 0) delete this; }
	}

This way the user doesn't have to check the documentation for the correct way to allocate this class, `new` will "just work":

	auto obj = new MyRCObject;

It's not like the user really has any choice in how to allocate the object anyway: implicit calls to `opRelease` will make sure things break if you use a different allocation method than what it expects.

- - -

In your example with a payload, I think it is bad style to free the payload in opRelease. I understand you can't free the payload in the destructor to account for the case the destructor is called by the GC, but that pattern won't work if you create a class derived from Widget adding another similar payload. Just saying.

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/

February 27, 2015
On 2/27/15 12:53 AM, Kagamin wrote:
> On Thursday, 26 February 2015 at 22:02:51 UTC, Andrei Alexandrescu wrote:
>>> So is the end game of dip25 and dip74 to not have to wrap types you
>>> intend to manage with RC like C++ but just design the classes/structs
>>> themselves around being RCed from the start?
>>
>> That is correct. Well as shown there are ways to design classes that
>> work both with RC and GC. -- Andrei
>
> If a class is meant to be refcounted at compile time, what's a
> difference from
> alias MyClass = RefCounted!MyClassImpl;
> // use MyClass instead
> except for it introduces an additional check for null and a branch?

The typechecking on RCOs is stricter, which makes them safe. -- Andrei
February 27, 2015
On 2/27/15 1:09 AM, ted wrote:
> Andrei Alexandrescu wrote:
>
>> http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and
>> discuss.
>>
>> Thanks,
>>
>> Andrei
>
> Trivial typos:
>
> struct, class, and closure types that have RCO members accommodate calls to
> Release during their destruction.
> s/Release/opRelease/
>
> Explicit casting to of from void* does not entail a call to opAddRef.
> s/of/or/
>
> also: s/opReleasecalls/opRelease calls/
>
> The examples in "Defining a reference counted object with deallocation",
> and "defining a type that owns resources" both define '_refs', and
> manipulate 'refs'.

Fixed, thanks!

> This is probably a really stupid question, but how does the 'new' work for
> an RCO. I assume it uses the GC memory allocation system, but must mark it
> as 'not for collection' (or similar), for the GC.free() call to work (as
> used in the examples).

DIP74 does not prescribe specific allocation techniques. They are left to the user.

One nice point of the design space would be to use the GC for allocation and early deallocation, in such a way that the GC is still able to collect cycles.

> Probably another silly question: How would the examples work with
> const/immutable (using examples in howtos)?
> e.g. const Widget a = new Widget;
>       auto b = a;	<-- mutable method Widget.opAddRef is not callable
> using a const object

This is tricky. I meant to discuss it; for now I planted a TODO.


Andrei

February 27, 2015
On Friday, 27 February 2015 at 13:36:33 UTC, Marc Schütz wrote:
> AddRef/Release is established COM terminology.

Which is from 1993, a period of time where MS was completely ignorant of everything outside MS.

Common resource-access terminology is:

acquire/release
retain/release
inc_ref/dec_ref
add_ref/remove_ref
down/up
wait/signal
P/V
open/close
enter/exit
begin/end
…

Notice the symmetry?
February 27, 2015
On 2/27/15 9:09 AM, Andrei Alexandrescu wrote:
> On 2/27/15 1:09 AM, ted wrote:

>> Probably another silly question: How would the examples work with
>> const/immutable (using examples in howtos)?
>> e.g. const Widget a = new Widget;
>>       auto b = a;    <-- mutable method Widget.opAddRef is not callable
>> using a const object
>
> This is tricky. I meant to discuss it; for now I planted a TODO.

Wouldn't you bless this mechanism of logical const the same way synchronized does?

-Steve
February 27, 2015
On 27 February 2015 at 07:50, Andrei Alexandrescu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss.
>
> Thanks,
>
> Andrei

I'm excited for this. I'm very happy with the approach.
I'm particularly happy that it is implemented as a pair of operators.
This is what I've always hoped it to look like.

My initial reactions are:

There's no mention of const/immutable...? Surely we can have RC immutable things right? I can't see how that works here... but it's very important.

I'm not clear on structs. What is the order for calls; postblit, opInc, opDec, destructor? 75% of my use cases today are thin structs that wrap C/C++ api's.

There's no mention of 'scope'. I presume functions that receive scope RC arguments will have the opportunity to have opAddRef/opRelesae elided around the call?

I wonder if some standard GetRefCount function should exist? Otherwise they will probably end up being named all sorts of different things. I guess I can't think of any value in a standardisation of the function otherwise though...
February 27, 2015
On 2/27/15 6:46 AM, Steven Schveighoffer wrote:
> On 2/27/15 9:09 AM, Andrei Alexandrescu wrote:
>> On 2/27/15 1:09 AM, ted wrote:
>
>>> Probably another silly question: How would the examples work with
>>> const/immutable (using examples in howtos)?
>>> e.g. const Widget a = new Widget;
>>>       auto b = a;    <-- mutable method Widget.opAddRef is not callable
>>> using a const object
>>
>> This is tricky. I meant to discuss it; for now I planted a TODO.
>
> Wouldn't you bless this mechanism of logical const the same way
> synchronized does?

Yes, it's a similar matter. -- Andrei