digitalmars.D - DIP74: Reference Counted Class Objects
- Andrei Alexandrescu (4/4) Feb 26 2015 http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and
- weaselcat (5/9) Feb 26 2015 So is the end game of dip25 and dip74 to not have to wrap types
- Andrei Alexandrescu (3/13) Feb 26 2015 That is correct. Well as shown there are ways to design classes that
- Kagamin (8/15) Feb 27 2015 If a class is meant to be refcounted at compile time, what's a
- Andrei Alexandrescu (2/14) Feb 27 2015 The typechecking on RCOs is stricter, which makes them safe. -- Andrei
- Brian Schott (12/16) Feb 26 2015 One of the first things that stood out to me is that "add ref" is
- Andrei Alexandrescu (3/7) Feb 26 2015 All - please PLEASE do not derail this into yet another debate about
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (13/23) Feb 27 2015 Using protocols rather than enforcing a particular implementation
- Kagamin (5/7) Feb 27 2015 That's about cache coherency, reference counting is only an
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (4/12) Feb 27 2015 Yeah, and that page documents why the Bill Gatish Microsoft
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (3/20) Feb 27 2015 AddRef/Release is established COM terminology.
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (16/17) Feb 27 2015 Which is from 1993, a period of time where MS was completely
- David Gileadi (6/23) Feb 27 2015 One reason for keeping COM terminology might be if
- Andrei Alexandrescu (4/29) Feb 27 2015 I explicitly avoided the COM names in order to avoid potential confusion...
- Jacob Carlborg (6/9) Feb 27 2015 It's still a breaking change. See one of my other replies [1] for a
- Andrei Alexandrescu (3/10) Feb 27 2015 I'm fine with breaking code of people who happen to use the names
- weaselcat (3/19) Feb 27 2015 Are op* considered reserved member names?
- Andrei Alexandrescu (2/19) Feb 27 2015 No. -- Andrei
- ketmar (5/6) Feb 27 2015 no. that's just the "we can break your code, and you can't break ours!"=...
- deadalnix (3/12) Feb 27 2015 I think this is justified to break the code here, but I share the
- Paolo Invernizzi (12/26) Feb 28 2015 I agree, as, well, this is starting to look pretty grotesque...
- Daniel Murphy (3/6) Feb 28 2015 This is an exaggeration...
- Paolo Invernizzi (7/13) Feb 28 2015 This is reality: both actual version of vibe.d and tango can't be
- Daniel Murphy (4/9) Feb 28 2015 Every project that overrides those methods is far from every project tha...
- Paolo Invernizzi (4/14) Feb 28 2015 I agree with you in that.
- Jacob Carlborg (4/7) Feb 28 2015 Add DWT to that list.
- Jacob Carlborg (5/7) Feb 28 2015 I don't think so because it's so easy to making it a non-breaking
- Matthias Bentrup (5/5) Feb 27 2015 When a function makes/destroys multiple references to an object
- Jacob Carlborg (5/7) Feb 28 2015 I don't think so because it's so easy to making it a non-breaking
- Andrei Alexandrescu (2/6) Feb 26 2015 It's a liberty still left to user code. -- Andrei
- Nick Treleaven (5/11) Feb 27 2015 ISTM nothrow would be a sensible starting point. That would simplify
- Andrei Alexandrescu (4/16) Feb 27 2015 I don't know of a compelling use case. Note that quite a few of the
- Brian Schott (7/11) Feb 26 2015 "This lowering assumes left-to-right evaluation of function
- Andrei Alexandrescu (2/14) Feb 26 2015 Yah, Walter mentioned these. We need to fix them. -- Andrei
- Brian Schott (3/4) Feb 26 2015 https://issues.dlang.org/show_bug.cgi?id=14228
- Johannes Pfau (37/43) Feb 26 2015 Looks very nice, some things to refine:
- Andrei Alexandrescu (14/49) Feb 26 2015 OK. I don't want to impose many limitations - let users explore
- Johannes Pfau (7/19) Feb 26 2015 Leaving the implementation of opAddRef/opRelease to the user really
- Andrei Alexandrescu (4/23) Feb 26 2015 Still looking for some sword to fall :o).
- Brian Schott (18/22) Feb 26 2015 "This is important because it limits what reference counted
- Andrei Alexandrescu (3/25) Feb 26 2015 Excellent notes, of which two important ones. Addressed - reload
- bearophile (8/14) Feb 26 2015 Defining only one of those methods needs to give a compile-time
- Andrei Alexandrescu (6/15) Feb 26 2015 Well types that define empty() and front() but not popFront() are not in...
- deadalnix (28/32) Feb 26 2015 "The compiler detects automatically and treats specially all
- Andrei Alexandrescu (2/14) Feb 26 2015 No, see below how typechecking is more strict for RCOs. -- Andrei
- deadalnix (4/11) Feb 26 2015 That is simply a rhetoric way to not admit failure of DIP25 and
- weaselcat (8/10) Feb 26 2015 Correct me if I'm wrong, but to me this presents itself as an
- Andrei Alexandrescu (6/15) Feb 26 2015 DIP74 allows defining objects outside the Object hierarchy that are
- H. S. Teoh via Digitalmars-d (8/10) Feb 26 2015 [...]
- Andrei Alexandrescu (2/9) Feb 26 2015 It does - but that might be fine with some applications. -- Andrei
- H. S. Teoh via Digitalmars-d (7/18) Feb 26 2015 But putting it into druntime imposes it on *all* applications, because
- Andrei Alexandrescu (6/21) Feb 26 2015 That's why I used "rigging" - meaning "equip for special purpose".
- H. S. Teoh via Digitalmars-d (8/32) Feb 26 2015 [...]
- anonymous (3/39) Feb 26 2015 We all pray you become less of a gaping asshole before youre in
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (6/56) Feb 27 2015 In fact, "we all" don't. Quite the opposite, several of the
- deadalnix (2/4) Feb 27 2015 Thank you for the compliment :)
- Walter Bright (2/3) Feb 28 2015 cut it out.
- ketmar (7/13) Feb 26 2015 this stinks in the same way as DIP25 stinks. right here: "Attention must...
- H. S. Teoh via Digitalmars-d (7/19) Feb 26 2015 [...]
- Andrei Alexandrescu (4/20) Feb 26 2015 The compiler will issue errors if returning ref to direct members. There...
- Andrei Alexandrescu (31/34) Feb 26 2015 To clarify this point, which I think is important, consider:
- deadalnix (3/41) Feb 26 2015 It is the same with a pointer to a struct.
- ketmar (3/21) Feb 26 2015 yep. this is the case for DIP25 too (see RCArray sample: it compiles=20
- Walter Bright (13/15) Feb 26 2015 Indeed, and the compiler will error out if you try that:
- H. S. Teoh via Digitalmars-d (31/51) Feb 27 2015 Huh? We weren't talking about that -- it's already a given that this
- Andrei Alexandrescu (8/11) Feb 27 2015 That is correct. However, the user is on the hook because her use of
- H. S. Teoh via Digitalmars-d (10/17) Feb 27 2015 [...]
- deadalnix (3/3) Feb 27 2015 Yup, it sound like the destruction should be delegated to the
- H. S. Teoh via Digitalmars-d (25/36) Feb 26 2015 [...]
- Rikki Cattermole (10/14) Feb 26 2015 Either I missed something or:
- Andrei Alexandrescu (8/23) Feb 26 2015 Yah, DIP74 is intentionally very "policy up, implementation down". It
- weaselcat (11/15) Feb 26 2015 P.S., am I too late to complain about the choice of 'return' in
- weaselcat (2/13) Feb 26 2015 hadn't*, Sorry.
- Jacob Carlborg (43/45) Feb 26 2015 * What will happen if these methods are defined on a class that is
- bearophile (5/13) Mar 01 2015 Assuming you want something like DIP74, this design design seems
- Taylor Hillegeist (20/33) Mar 02 2015 So, I don't know a huge amount about this subject. aka. (hold my
- Jacob Carlborg (10/12) Feb 26 2015 To me this looks like ARC (Automated Reference Counting). I know that
- ted (20/26) Feb 27 2015 Trivial typos:
- Andrei Alexandrescu (9/35) Feb 27 2015 DIP74 does not prescribe specific allocation techniques. They are left
- Steven Schveighoffer (4/11) Feb 27 2015 Wouldn't you bless this mechanism of logical const the same way
- Andrei Alexandrescu (2/13) Feb 27 2015 Yes, it's a similar matter. -- Andrei
- ted (7/56) Feb 27 2015 I'm still a bit confused here: the examples in DIP74 showed the freeing ...
- deadalnix (9/13) Feb 27 2015 That is on of the 2 main problems with this DIP. The memory
- Andrei Alexandrescu (6/12) Feb 27 2015 The GC allows both manual freeing and via tracing. So after allocating
- Orvid King (15/15) Feb 27 2015 From the perspective of someone mostly indifferent to the support
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (15/17) Feb 27 2015 Destroy:
- Zach the Mystic (15/19) Feb 27 2015 It's kind of funny that you were looking for an edge to my safety
- Michel Fortin (30/31) Feb 27 2015 Looks good in general.
- Manu via Digitalmars-d (19/23) Feb 27 2015 I'm excited for this. I'm very happy with the approach.
- Andrei Alexandrescu (13/26) Feb 27 2015 Structs don't get any special treatment with DIP74, only classes and
- Manu via Digitalmars-d (8/25) Feb 27 2015 Well this is the case of the highest value to me, and DIP74 offers nothi...
- Andrei Alexandrescu (2/3) Feb 27 2015 For structs you use postblit and destructors. -- Andrei
- Manu via Digitalmars-d (3/8) Feb 28 2015 That doesn't work now, and I don't see why that would suddenly work unde...
- Andrei Alexandrescu (3/13) Feb 28 2015 Per DIP25 and RCSlice, you may define a safe struct with reference
- Andrei Alexandrescu (8/12) Feb 27 2015 Ah, I think you mean structs that have a class member? The compiler will...
- Manu via Digitalmars-d (15/28) Feb 28 2015 Well, not specifically. I mean any struct that has any indirect member(/...
- Andrei Alexandrescu (2/6) Feb 28 2015 The short answer is that probably won't happen. -- Andrei
- Manu via Digitalmars-d (26/33) Feb 28 2015 *sigh* ... ever, or in DIP74?
- Andrei Alexandrescu (9/30) Feb 28 2015 struct X
- Manu via Digitalmars-d (5/44) Feb 28 2015 You've conveniently ignored the word 'efficient'.
- Andrei Alexandrescu (6/56) Feb 28 2015 Inserting calls to opAddRef and opRelease, and the rules that allow
- Manu via Digitalmars-d (10/76) Feb 28 2015 The most important case to be elided is the function call case.
- Andrei Alexandrescu (10/28) Feb 28 2015 RefCounted has been in there for quite a while and worked with structs.
- John Colvin (4/7) Mar 01 2015 Yes please. I'd be very interested in hearing any thoughts you
- Andrei Alexandrescu (22/30) Mar 01 2015 One that comes to mind is: if (a) a copy b of a struct object a is
- ponce (6/10) Feb 27 2015 LGTM, it is great to see something done for deterministic class
- Volodymyr (3/7) Mar 02 2015 opAddRef/opRelease breaks SOLID's single responsibility principle.
- Volodymyr (20/24) Mar 03 2015 With opAddRef/opRelease class does respondible for its
- Andrei Alexandrescu (5/30) Mar 03 2015 Correct. That's a tactical matter that can be addressed e.g. with mixin
- Volodymyr (7/48) Mar 04 2015 Why couldn't? Let's for all @return (this) functions make
- Volodymyr (40/40) Mar 04 2015 Implicit conversion to supertypes (class or interface) is allowed
- Andrei Alexandrescu (6/11) Mar 04 2015 That also entails an implicit conversion. To clarify, I added this to
- bitwise (3/3) Mar 04 2015 After looking at DIP74, it seems that there is no way to create a
- Andrei Alexandrescu (4/7) Mar 04 2015 DIP74 aims at not disallowing weak references whilst leaving it to
- bitwise (63/73) Mar 04 2015 I suppose you could add "getWeak()" and "releaseWeak()" to a ref
- Andrei Alexandrescu (3/5) Mar 04 2015 My initial attempt would be to see if opAddRef and opRelease defined by
http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. Thanks, Andrei
Feb 26 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, AndreiSo 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?
Feb 26 2015
On 2/26/15 2:01 PM, weaselcat wrote:On Thursday, 26 February 2015 at 21:50:56 UTC, Andrei Alexandrescu wrote:That is correct. Well as shown there are ways to design classes that work both with RC and GC. -- Andreihttp://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. Thanks, AndreiSo 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?
Feb 26 2015
On Thursday, 26 February 2015 at 22:02:51 UTC, Andrei Alexandrescu wrote: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?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
Feb 27 2015
On 2/27/15 12:53 AM, Kagamin wrote:On Thursday, 26 February 2015 at 22:02:51 UTC, Andrei Alexandrescu wrote:The typechecking on RCOs is stricter, which makes them safe. -- AndreiIf 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?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
Feb 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, AndreiOne 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 The DIP states that "Any attributes are allowed on these methods.", but later states "The complexity of this code underlies the importance of making opAddRef and especially opRelease nothrow". Should the DIP require that these two functions be marked nothrow?
Feb 26 2015
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, opReleaseAll - please PLEASE do not derail this into yet another debate about which names are best. -- Andrei
Feb 26 2015
On Thursday, 26 February 2015 at 22:04:09 UTC, Andrei Alexandrescu wrote:On 2/26/15 2:03 PM, Brian Schott wrote:Using protocols rather than enforcing a particular implementation is nice, but D needs to stop reinventing terminology and syntax matters. Acquire/Release: https://msdn.microsoft.com/en-us/library/windows/hardware/ff540496%28v=vs.85%29.aspx Retain/Release: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html AutoRelease pools / Drain: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSAutoreleasePool_Class/index.html#//apple_ref/occ/instm/NSAutoreleasePool/drain Antonyms for "release": http://www.merriam-webster.com/thesaurus/release[verb]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, opReleaseAll - please PLEASE do not derail this into yet another debate about which names are best. -- Andrei
Feb 27 2015
On Friday, 27 February 2015 at 08:26:14 UTC, Ola Fosheim Grøstad wrote:Acquire/Release: https://msdn.microsoft.com/en-us/library/windows/hardware/ff540496%28v=vs.85%29.aspxThat's about cache coherency, reference counting is only an illustration. And this is about reference counting: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680509.aspx
Feb 27 2015
On Friday, 27 February 2015 at 08:56:49 UTC, Kagamin wrote:On Friday, 27 February 2015 at 08:26:14 UTC, Ola Fosheim Grøstad wrote:Yeah, and that page documents why the Bill Gatish Microsoft sucks. They used to invent their own incoherent standards/terminology...Acquire/Release: https://msdn.microsoft.com/en-us/library/windows/hardware/ff540496%28v=vs.85%29.aspxThat's about cache coherency, reference counting is only an illustration. And this is about reference counting: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680509.aspx
Feb 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:AddRef/Release is established COM terminology.On 2/26/15 2:03 PM, Brian Schott wrote:Using protocols rather than enforcing a particular implementation is nice, but D needs to stop reinventing terminology and syntax matters. -- snip --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, opReleaseAll - please PLEASE do not derail this into yet another debate about which names are best. -- Andrei
Feb 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?
Feb 27 2015
On 2/27/15 6:36 AM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net>" wrote:On Friday, 27 February 2015 at 08:26:14 UTC, Ola Fosheim Grøstad wrote:One reason for keeping COM terminology might be if std.c.windows.com.IUnknown can automatically take advantage of DIP74. Of course this could also be a downside—would DIP74 break existing COM code in D?On Thursday, 26 February 2015 at 22:04:09 UTC, Andrei Alexandrescu wrote:AddRef/Release is established COM terminology.On 2/26/15 2:03 PM, Brian Schott wrote:Using protocols rather than enforcing a particular implementation is nice, but D needs to stop reinventing terminology and syntax matters. -- snip --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, opReleaseAll - please PLEASE do not derail this into yet another debate about which names are best. -- Andrei
Feb 27 2015
On 2/27/15 10:34 AM, David Gileadi wrote:On 2/27/15 6:36 AM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net>" wrote:I explicitly avoided the COM names in order to avoid potential confusion and code breakage. People can easily add IUnknownAuto that does the forwarding. -- AndreiOn Friday, 27 February 2015 at 08:26:14 UTC, Ola Fosheim Grøstad wrote:One reason for keeping COM terminology might be if std.c.windows.com.IUnknown can automatically take advantage of DIP74. Of course this could also be a downside—would DIP74 break existing COM code in D?On Thursday, 26 February 2015 at 22:04:09 UTC, Andrei Alexandrescu wrote:AddRef/Release is established COM terminology.On 2/26/15 2:03 PM, Brian Schott wrote:Using protocols rather than enforcing a particular implementation is nice, but D needs to stop reinventing terminology and syntax matters. -- snip --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, opReleaseAll - please PLEASE do not derail this into yet another debate about which names are best. -- Andrei
Feb 27 2015
On 2015-02-27 19:38, Andrei Alexandrescu wrote:I explicitly avoided the COM names in order to avoid potential confusion and code breakage. People can easily add IUnknownAuto that does the forwarding. -- AndreiIt's still a breaking change. See one of my other replies [1] for a possible solution. [1] http://forum.dlang.org/post/mcp5nu$1nus$1 digitalmars.com -- /Jacob Carlborg
Feb 27 2015
On 2/27/15 11:58 AM, Jacob Carlborg wrote:On 2015-02-27 19:38, Andrei Alexandrescu wrote:I'm fine with breaking code of people who happen to use the names opAddRef and opRelease. -- AndreiI explicitly avoided the COM names in order to avoid potential confusion and code breakage. People can easily add IUnknownAuto that does the forwarding. -- AndreiIt's still a breaking change. See one of my other replies [1] for a possible solution. [1] http://forum.dlang.org/post/mcp5nu$1nus$1 digitalmars.com
Feb 27 2015
On Friday, 27 February 2015 at 20:04:27 UTC, Andrei Alexandrescu wrote:On 2/27/15 11:58 AM, Jacob Carlborg wrote:Are op* considered reserved member names?On 2015-02-27 19:38, Andrei Alexandrescu wrote:I'm fine with breaking code of people who happen to use the names opAddRef and opRelease. -- AndreiI explicitly avoided the COM names in order to avoid potential confusion and code breakage. People can easily add IUnknownAuto that does the forwarding. -- AndreiIt's still a breaking change. See one of my other replies [1] for a possible solution. [1] http://forum.dlang.org/post/mcp5nu$1nus$1 digitalmars.com
Feb 27 2015
On 2/27/15 12:13 PM, weaselcat wrote:On Friday, 27 February 2015 at 20:04:27 UTC, Andrei Alexandrescu wrote:No. -- AndreiOn 2/27/15 11:58 AM, Jacob Carlborg wrote:Are op* considered reserved member names?On 2015-02-27 19:38, Andrei Alexandrescu wrote:I'm fine with breaking code of people who happen to use the names opAddRef and opRelease. -- AndreiI explicitly avoided the COM names in order to avoid potential confusion and code breakage. People can easily add IUnknownAuto that does the forwarding. -- AndreiIt's still a breaking change. See one of my other replies [1] for a possible solution. [1] http://forum.dlang.org/post/mcp5nu$1nus$1 digitalmars.com
Feb 27 2015
On Fri, 27 Feb 2015 20:13:31 +0000, weaselcat wrote:Are op* considered reserved member names?no. that's just the "we can break your code, and you can't break ours!"=20 it's funny how the argument "we will not break user's code" pops up even=20 for breaking invalid code, but completely ignored for perfectly valid=20 code not forbidden by the specs.=
Feb 27 2015
On Saturday, 28 February 2015 at 03:49:04 UTC, ketmar wrote:On Fri, 27 Feb 2015 20:13:31 +0000, weaselcat wrote:I think this is justified to break the code here, but I share the irritation in front of the inconsistency.Are op* considered reserved member names?no. that's just the "we can break your code, and you can't break ours!" it's funny how the argument "we will not break user's code" pops up even for breaking invalid code, but completely ignored for perfectly valid code not forbidden by the specs.
Feb 27 2015
On Saturday, 28 February 2015 at 05:57:19 UTC, deadalnix wrote:On Saturday, 28 February 2015 at 03:49:04 UTC, ketmar wrote:I agree, as, well, this is starting to look pretty grotesque... The druntime/phobos 2.067 are breaking every piece of software out there that relies on core.sync or concurrency.scheduler, vibe and tango included. I admit that breakages coming from phobos' changes are pretty different from a breakages coming from compiler changes, but we are talking about the runtime library also. Oh well, who cares: my backlog of D code tasks at work is too long to start complaining... let's go back to the code... --- PaoloOn Fri, 27 Feb 2015 20:13:31 +0000, weaselcat wrote:I think this is justified to break the code here, but I share the irritation in front of the inconsistency.Are op* considered reserved member names?no. that's just the "we can break your code, and you can't break ours!" it's funny how the argument "we will not break user's code" pops up even for breaking invalid code, but completely ignored for perfectly valid code not forbidden by the specs.
Feb 28 2015
"Paolo Invernizzi" wrote in message news:wkcsqtzjqybortkabpkv forum.dlang.org...The druntime/phobos 2.067 are breaking every piece of software out there that relies on core.sync or concurrency.scheduler, vibe and tango included.This is an exaggeration...
Feb 28 2015
On Saturday, 28 February 2015 at 10:30:55 UTC, Daniel Murphy wrote:"Paolo Invernizzi" wrote in message news:wkcsqtzjqybortkabpkv forum.dlang.org...This is reality: both actual version of vibe.d and tango can't be compiled with 2.067, and it's a reality that this put some real work to do on the shoulders of the maintainers. --- PaoloThe druntime/phobos 2.067 are breaking every piece of software out there that relies on core.sync or concurrency.scheduler, vibe and tango included.This is an exaggeration...
Feb 28 2015
"Paolo Invernizzi" wrote in message news:avsvjanhckbcjttaolwc forum.dlang.org...The druntime/phobos 2.067 are breaking every piece of software out there that relies on core.sync or concurrency.scheduler,This is reality: both actual version of vibe.d and tango can't be compiled with 2.067, and it's a reality that this put some real work to do on the shoulders of the maintainers.Every project that overrides those methods is far from every project that relies on core.sync or core.scheduler.
Feb 28 2015
On Saturday, 28 February 2015 at 11:03:14 UTC, Daniel Murphy wrote:"Paolo Invernizzi" wrote in message news:avsvjanhckbcjttaolwc forum.dlang.org...I agree with you in that. /PThe druntime/phobos 2.067 are breaking every piece of software out there that relies on core.sync or concurrency.scheduler,This is reality: both actual version of vibe.d and tango can't be compiled with 2.067, and it's a reality that this put some real work to do on the shoulders of the maintainers.Every project that overrides those methods is far from every project that relies on core.sync or core.scheduler.
Feb 28 2015
On 2015-02-28 10:41, Paolo Invernizzi wrote:I agree, as, well, this is starting to look pretty grotesque... The druntime/phobos 2.067 are breaking every piece of software out there that relies on core.sync or concurrency.scheduler, vibe and tango included.Add DWT to that list. -- /Jacob Carlborg
Feb 28 2015
On 2015-02-28 06:57, deadalnix wrote:I think this is justified to break the code here, but I share the irritation in front of the inconsistency.I don't think so because it's so easy to making it a non-breaking change, i.e. require a compiler recognized UDA to enable the functionality. -- /Jacob Carlborg
Feb 28 2015
When a function makes/destroys multiple references to an object it should always be safe to coalesce all AddRefs into the first AddRef and all Releases to into the last Release call. This could be a small performance win, but opAddRef/opRelease would need the count as argument or maybe as template parameter.
Feb 27 2015
On 2015-02-27 21:04, Andrei Alexandrescu wrote:I'm fine with breaking code of people who happen to use the names opAddRef and opRelease. -- AndreiI don't think so because it's so easy to making it a non-breaking change, i.e. require a compiler recognized UDA to enable the functionality. -- /Jacob Carlborg
Feb 28 2015
On 2/26/15 2:03 PM, Brian Schott wrote:The DIP states that "Any attributes are allowed on these methods.", but later states "The complexity of this code underlies the importance of making opAddRef and especially opRelease nothrow". Should the DIP require that these two functions be marked nothrow?It's a liberty still left to user code. -- Andrei
Feb 26 2015
On 26/02/2015 22:04, Andrei Alexandrescu wrote:On 2/26/15 2:03 PM, Brian Schott wrote:ISTM nothrow would be a sensible starting point. That would simplify compiler implementation and avoid invisible inefficiency in user code. Shouldn't we wait for a compelling use case for throwing in these functions before supporting it?The DIP states that "Any attributes are allowed on these methods.", but later states "The complexity of this code underlies the importance of making opAddRef and especially opRelease nothrow". Should the DIP require that these two functions be marked nothrow?It's a liberty still left to user code. -- Andrei
Feb 27 2015
On 2/27/15 9:24 AM, Nick Treleaven wrote:On 26/02/2015 22:04, Andrei Alexandrescu wrote:I don't know of a compelling use case. Note that quite a few of the implementations complications remain; the surrounding code may still throw. -- AndreiOn 2/26/15 2:03 PM, Brian Schott wrote:ISTM nothrow would be a sensible starting point. That would simplify compiler implementation and avoid invisible inefficiency in user code. Shouldn't we wait for a compelling use case for throwing in these functions before supporting it?The DIP states that "Any attributes are allowed on these methods.", but later states "The complexity of this code underlies the importance of making opAddRef and especially opRelease nothrow". Should the DIP require that these two functions be marked nothrow?It's a liberty still left to user code. -- Andrei
Feb 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"This lowering assumes left-to-right evaluation of function parameters." -DIP 74 "The following binary expressions are evaluated in an implementation-defined order: AssignExpression, function arguments" - http://dlang.org/expression.html
Feb 26 2015
On 2/26/15 2:17 PM, Brian Schott wrote:On Thursday, 26 February 2015 at 21:50:56 UTC, Andrei Alexandrescu wrote:Yah, Walter mentioned these. We need to fix them. -- Andreihttp://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. Thanks, Andrei"This lowering assumes left-to-right evaluation of function parameters." -DIP 74 "The following binary expressions are evaluated in an implementation-defined order: AssignExpression, function arguments" - http://dlang.org/expression.html
Feb 26 2015
On Thursday, 26 February 2015 at 22:22:53 UTC, Andrei Alexandrescu wrote:Yah, Walter mentioned these. We need to fix them. -- Andreihttps://issues.dlang.org/show_bug.cgi?id=14228
Feb 26 2015
Am Thu, 26 Feb 2015 13:50:55 -0800 schrieb Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. Thanks, AndreiLooks very nice, some things to refine: "Any attributes are allowed on these methods." * Should safe and trusted by disallowed as " safe code may not issue explicit calls to opAddRef/opRelease"? * Probably also add a note here that the functions must be inverse and a note that they should be nothrow and/or final for performance. "This DIP proposes safe reference counted class objects (including exceptions)" * Unfortunately the DIP doesn't talk about exceptions ;-) Will we simply make Throwable a RCO? "considers that opRelease is the inverse of opAddRef, and therefore is at liberty to elide pairs of calls" * Nice, but does that mean that reference-counted classes are now superior to reference counted structs? It would be nice if the compiler could also detect opRelease/opAddRef in structs. We could still require user code to call these manually in postblits etc but recognizing them would allow eliding pairs. Also a more general question: What are the most important memory management strategies and which are handled by DIP25+DIP74? * GC Of course supported * RC Supported with DIP74. I think this could also be considered as ARC. If not, what is missing from DIP74 compared to ARC? * Scoped (useful for stack objects) Can 'return' be used to implement something which allocates a class on the stack and prevents escaping references? I guess a Scope struct allocating in place + a function returning a reference to the class with 'return' (+ alias this) would work? * Owned Supported by the member variables lifetime = parent lifetime rule? * Unique ? * ?
Feb 26 2015
On 2/26/15 2:39 PM, Johannes Pfau wrote:Looks very nice, some things to refine: "Any attributes are allowed on these methods." * Should safe and trusted by disallowed as " safe code may not issue explicit calls to opAddRef/opRelease"? * Probably also add a note here that the functions must be inverse and a note that they should be nothrow and/or final for performance.OK. I don't want to impose many limitations - let users explore possibilities. I added the recommendation."This DIP proposes safe reference counted class objects (including exceptions)" * Unfortunately the DIP doesn't talk about exceptions ;-) Will we simply make Throwable a RCO?Yes."considers that opRelease is the inverse of opAddRef, and therefore is at liberty to elide pairs of calls" * Nice, but does that mean that reference-counted classes are now superior to reference counted structs? It would be nice if the compiler could also detect opRelease/opAddRef in structs. We could still require user code to call these manually in postblits etc but recognizing them would allow eliding pairs.That's already taken care of - this(this) and ~this() are considered complementary.Also a more general question: What are the most important memory management strategies and which are handled by DIP25+DIP74? * GC Of course supported * RC Supported with DIP74. I think this could also be considered as ARC. If not, what is missing from DIP74 compared to ARC?Unless something major we didn't think of is found with DIP25 and DIP74, it's not impossible we found the perfect shade. Not only we'll offer automatic reference counting, but we'll allow people do define types that are usable in safe code that do that.* Scoped (useful for stack objects) Can 'return' be used to implement something which allocates a class on the stack and prevents escaping references? I guess a Scope struct allocating in place + a function returning a reference to the class with 'return' (+ alias this) would work?Yah, DIP74 can be directly used to make "scope w = new Widget;" work. But we'll address that in a distinct DIP in order to not bloat this one.* Owned Supported by the member variables lifetime = parent lifetime rule? * Unique ? * ?Let's see. Andrei
Feb 26 2015
Am Thu, 26 Feb 2015 14:53:16 -0800 schrieb Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:On 2/26/15 2:39 PM, Johannes Pfau wrote:Leaving the implementation of opAddRef/opRelease to the user really opens some interesting possibilities. Wrapping manually reference-counted C libraries is a rather obvious one but there are probably more interesting cases. Overall this proposal looks very nice :-)Looks very nice, some things to refine: "Any attributes are allowed on these methods." * Should safe and trusted by disallowed as " safe code may not issue explicit calls to opAddRef/opRelease"? * Probably also add a note here that the functions must be inverse and a note that they should be nothrow and/or final for performance.OK. I don't want to impose many limitations - let users explore possibilities. I added the recommendation.
Feb 26 2015
On 2/26/15 3:12 PM, Johannes Pfau wrote:Am Thu, 26 Feb 2015 14:53:16 -0800 schrieb Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:Yah, this should dovetail real nice with allocators too.On 2/26/15 2:39 PM, Johannes Pfau wrote:Leaving the implementation of opAddRef/opRelease to the user really opens some interesting possibilities. Wrapping manually reference-counted C libraries is a rather obvious one but there are probably more interesting cases.Looks very nice, some things to refine: "Any attributes are allowed on these methods." * Should safe and trusted by disallowed as " safe code may not issue explicit calls to opAddRef/opRelease"? * Probably also add a note here that the functions must be inverse and a note that they should be nothrow and/or final for performance.OK. I don't want to impose many limitations - let users explore possibilities. I added the recommendation.Overall this proposal looks very nice :-)Still looking for some sword to fall :o). Andrei
Feb 26 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"This is important because it limits what reference counted types." - I'm not sure what this means. "The methods may or may not be final or inherited." - Should this be "final or virtual"? "Any attributes are allowed on these methods." - I'm going to have to write a static analysis warning for marking these "const". "Call is inserted only if the reference is not null" - Should this be "Call is executed only if the reference is not null"? "</tt>opRelease</tt>" - Some markup escaped into the wild! "The same is achievable with RCOs by means of disable opAddRef();" - Suggestion: add some text stating that opRelease() must still be present and implemented. "Attention must be paid to annotate with return all functions that return references to owned data" -> "Attention must be paid to annotate all functions that return references to owned data with `return`"
Feb 26 2015
On 2/26/15 2:42 PM, Brian Schott wrote:On Thursday, 26 February 2015 at 21:50:56 UTC, Andrei Alexandrescu wrote:Excellent notes, of which two important ones. Addressed - reload http://wiki.dlang.org/DIP74 - thanks! -- Andreihttp://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. Thanks, Andrei"This is important because it limits what reference counted types." - I'm not sure what this means. "The methods may or may not be final or inherited." - Should this be "final or virtual"? "Any attributes are allowed on these methods." - I'm going to have to write a static analysis warning for marking these "const". "Call is inserted only if the reference is not null" - Should this be "Call is executed only if the reference is not null"? "</tt>opRelease</tt>" - Some markup escaped into the wild! "The same is achievable with RCOs by means of disable opAddRef();" - Suggestion: add some text stating that opRelease() must still be present and implemented. "Attention must be paid to annotate with return all functions that return references to owned data" -> "Attention must be paid to annotate all functions that return references to owned data with `return`"
Feb 26 2015
Andrei Alexandrescu:The compiler detects automatically and treats specially all classes and interfaces that define the following two methods:<Defining only one of those methods needs to give a compile-time error.This lowering assumes left-to-right evaluation of function parameters.<Is this currently enforced in all D compilers?This DIP allows defining reference counted class objects that are usable in safe code. However, it does not enforce safety.<And do you plan to later design what's needed to enforce their safety? Bye, bearophile
Feb 26 2015
On 2/26/15 3:19 PM, bearophile wrote:Andrei Alexandrescu:Well types that define empty() and front() but not popFront() are not in error, either.The compiler detects automatically and treats specially all classes and interfaces that define the following two methods:<Defining only one of those methods needs to give a compile-time error.No, though there have been improvements. Brian submitted an(other) issue.This lowering assumes left-to-right evaluation of function parameters.<Is this currently enforced in all D compilers?Not at this time. AndreiThis DIP allows defining reference counted class objects that are usable in safe code. However, it does not enforce safety.<And do you plan to later design what's needed to enforce their safety?
Feb 26 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"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.
Feb 26 2015
On 2/26/15 4:09 PM, deadalnix wrote:On Thursday, 26 February 2015 at 21:50:56 UTC, Andrei Alexandrescu wrote:No, see below how typechecking is more strict for RCOs. -- Andreihttp://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.
Feb 26 2015
On Friday, 27 February 2015 at 00:12:32 UTC, Andrei Alexandrescu wrote:That is simply a rhetoric way to not admit failure of DIP25 and DIP69.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.No, see below how typechecking is more strict for RCOs. -- Andrei
Feb 26 2015
On Fri, 27 Feb 2015 00:36:41 +0000, deadalnix wrote:On Friday, 27 February 2015 at 00:12:32 UTC, Andrei Alexandrescu wrote:this stinks in the same way as DIP25 stinks. right here: "Attention must=20 be paid to annotate all functions returning references to owned data with=20 return." this single thing will bring enormous pile of bugs. i want to=20 have $1 each time someone will be hit by the bug "oh, i forgot to put=20 `return` there!", so i can drop my work and do nothing 'till the end of=20 my life.==20 That is simply a rhetoric way to not admit failure of DIP25 and DIP69.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.No, see below how typechecking is more strict for RCOs. -- Andrei
Feb 26 2015
ooops, sorry, deadalnix, i was meant to post this as the answer to the OP=20 post.=
Feb 26 2015
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.
Feb 26 2015
On 2/26/15 5:41 PM, weaselcat wrote:On Friday, 27 February 2015 at 00:10:00 UTC, deadalnix wrote: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. AndreiNo 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.
Feb 26 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.
Feb 26 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: [...]It does - but that might be fine with some applications. -- AndreiAn 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?
Feb 26 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: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.On Thu, Feb 26, 2015 at 05:44:36PM -0800, Andrei Alexandrescu via Digitalmars-d wrote: [...]It does - but that might be fine with some applications. -- AndreiAn 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?
Feb 26 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: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). AndreiOn 2/26/15 5:59 PM, H. S. Teoh via Digitalmars-d wrote: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.On Thu, Feb 26, 2015 at 05:44:36PM -0800, Andrei Alexandrescu via Digitalmars-d wrote: [...]It does - but that might be fine with some applications. -- AndreiAn 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?
Feb 26 2015
On Thu, Feb 26, 2015 at 06:39:12PM -0800, Andrei Alexandrescu via Digitalmars-d wrote:On 2/26/15 6:21 PM, H. S. Teoh via Digitalmars-d wrote:[...] Ahhh, I see what you mean now. That's an interesting idea... I suppose people like Manu could like to do something like this to get ARC by default, for example. T -- Do not reason with the unreasonable; you lose by definition.On Thu, Feb 26, 2015 at 06:06:04PM -0800, Andrei Alexandrescu via Digitalmars-d wrote: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).On 2/26/15 5:59 PM, H. S. Teoh via Digitalmars-d wrote: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.On Thu, Feb 26, 2015 at 05:44:36PM -0800, Andrei Alexandrescu via Digitalmars-d wrote: [...]It does - but that might be fine with some applications. -- AndreiAn 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?
Feb 26 2015
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:We all pray you become less of a gaping asshole before youre in charge of anything.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.
Feb 26 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: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.On Thursday, 26 February 2015 at 21:50:56 UTC, Andrei Alexandrescu wrote:We all pray you become less of a gaping asshole before youre in charge of anything.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.
Feb 27 2015
On Friday, 27 February 2015 at 07:44:18 UTC, anonymous wrote:We all pray you become less of a gaping asshole before youre in charge of anything.Thank you for the compliment :)
Feb 27 2015
On 2/26/2015 11:44 PM, anonymous wrote:We all pray you become less of a [...]cut it out.
Feb 28 2015
On Thu, 26 Feb 2015 13:50:55 -0800, Andrei Alexandrescu wrote:http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. =20 Thanks, =20 Andreithis stinks in the same way as DIP25 stinks. right here: "Attention must=20 be paid to annotate all functions returning references to owned data with=20 return." this single thing will bring enormous pile of bugs. i want to=20 have $1 each time someone will be hit by the bug "oh, i forgot to put=20 `return` there!", so i can drop my work and do nothing 'till the end of=20 my life.=
Feb 26 2015
On Fri, Feb 27, 2015 at 12:59:38AM +0000, ketmar via Digitalmars-d wrote:On Thu, 26 Feb 2015 13:50:55 -0800, Andrei Alexandrescu wrote:[...] Wait, are you saying that forgetting the 'return' annotation will still compile without any warning?? Wow, that's ... not nice. :-( T -- Those who don't understand D are condemned to reinvent it, poorly. -- Daniel Nhttp://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. Thanks, Andreithis stinks in the same way as DIP25 stinks. right here: "Attention must be paid to annotate all functions returning references to owned data with return." this single thing will bring enormous pile of bugs.
Feb 26 2015
On 2/26/15 5:37 PM, H. S. Teoh via Digitalmars-d wrote:On Fri, Feb 27, 2015 at 12:59:38AM +0000, ketmar via Digitalmars-d 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. -- AndreiOn Thu, 26 Feb 2015 13:50:55 -0800, Andrei Alexandrescu wrote:[...] Wait, are you saying that forgetting the 'return' annotation will still compile without any warning?? Wow, that's ... not nice. :-(http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. Thanks, Andreithis stinks in the same way as DIP25 stinks. right here: "Attention must be paid to annotate all functions returning references to owned data with return." this single thing will bring enormous pile of bugs.
Feb 26 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. -- AndreiTo 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
Feb 26 2015
On Friday, 27 February 2015 at 02:05:33 UTC, Andrei Alexandrescu wrote:On 2/26/15 5:43 PM, Andrei Alexandrescu wrote:It is the same with a pointer to a struct.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. -- AndreiTo 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
Feb 26 2015
On Thu, 26 Feb 2015 17:37:46 -0800, H. S. Teoh via Digitalmars-d wrote:On Fri, Feb 27, 2015 at 12:59:38AM +0000, ketmar via Digitalmars-d wrote:yep. this is the case for DIP25 too (see RCArray sample: it compiles=20 perfectly fine without `return`).=On Thu, 26 Feb 2015 13:50:55 -0800, Andrei Alexandrescu wrote: =20[...] =20 Wait, are you saying that forgetting the 'return' annotation will still compile without any warning?? Wow, that's ... not nice. :-(http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. =20 Thanks, =20 Andrei=20 this stinks in the same way as DIP25 stinks. right here: "Attention must be paid to annotate all functions returning references to owned data with return." this single thing will bring enormous pile of bugs.
Feb 26 2015
On 2/26/2015 5:37 PM, H. S. Teoh via Digitalmars-d wrote:Wait, are you saying that forgetting the 'return' annotation will still compile without any warning?? Wow, that's ... not nice. :-(Indeed, and the compiler will error out if you try that: --- struct S { int x; } ref int foo(ref S s) { return s.x; } --- dmd -c foo -dip25 foo.d(7): Error: escaping reference to local ref variable s There'd be no point to DIP25 if it didn't.
Feb 26 2015
On Thu, Feb 26, 2015 at 11:35:55PM -0800, Walter Bright via Digitalmars-d wrote:On 2/26/2015 5:37 PM, H. S. Teoh via Digitalmars-d wrote:Huh? We weren't talking about that -- it's already a given that this case works, otherwise DIP25 would truly have no point. The problematic case comes from the manually-managed array member that you can freely return, yet it may become a dangling reference once opRelease deallocates it: class S { int[] data; int[] foo() { return data; } // <-- happily compiles void opAddRef() { ... } void opRelease() { ... GC.free(data); // <-- uh oh } } int[] fun() { S s = /* create instance of S */ return s.foo(); // s goes out of scope here, and opRelease() cleans up // but we now have an escaping reference to s.data } void main() { int[] dangling = fun(); dangling[0] = 1; // kaboom } S.foo() should have been annotated with 'return', but the programmer forgot and the compiler still accepts the code without any warnings, thereby violating safe. T -- Bomb technician: If I'm running, try to keep up.Wait, are you saying that forgetting the 'return' annotation will still compile without any warning?? Wow, that's ... not nice. :-(Indeed, and the compiler will error out if you try that: --- struct S { int x; } ref int foo(ref S s) { return s.x; } --- dmd -c foo -dip25 foo.d(7): Error: escaping reference to local ref variable s There'd be no point to DIP25 if it didn't.
Feb 27 2015
On 2/27/15 7:42 AM, H. S. Teoh via Digitalmars-d wrote:S.foo() should have been annotated with 'return', but the programmer forgot and the compiler still accepts the code without any warnings, thereby violating safe.That is correct. However, the user is on the hook because her use of trusted when deallocating the array. I think the right thing to do about owned data is to give it its own abstraction, and plant it in the standard library. RCSlice would be an obvious go-to structure. Could you consider defining an OwnedSlice and see how far you can get? Andrei
Feb 27 2015
On Fri, Feb 27, 2015 at 08:00:20AM -0800, Andrei Alexandrescu via Digitalmars-d wrote:On 2/27/15 7:42 AM, H. S. Teoh via Digitalmars-d wrote:[...] Which shows just how dangerous trusted is. :-P But that's a good point. The use of trusted in theory should have raised red flags that the programmer needs to be careful here. There's also the case of using malloc/free to allocate the array, but I suppose that falls in the same category. T -- A bend in the road is not the end of the road unless you fail to make the turn. -- Brian WhiteS.foo() should have been annotated with 'return', but the programmer forgot and the compiler still accepts the code without any warnings, thereby violating safe.That is correct. However, the user is on the hook because her use of trusted when deallocating the array.
Feb 27 2015
Yup, it sound like the destruction should be delegated to the destructor. Maybe the release method could return the refcount ?
Feb 27 2015
On Thu, Feb 26, 2015 at 01:50:55PM -0800, Andrei Alexandrescu via Digitalmars-d wrote:http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss.[...] Under "Rules":The complexity of this code underlies the importance of making^^^^^^^^^ Should be "underlines"opAddRef and especially opRelease nothrow. In that case the scope(failure) statement may be elided.Under "Rules":struct, class, and closure types that have RCO members accommodate calls to Release during their destruction.This is unclear to me. What exactly is the semantics of "accomodate calls to Release"? And what is "Release"? Did you mean opRelease? Also, the code example following is also unclear; since struct A has no RCO members that I can see, does that mean the calling sequences (labelled 1-9) apply to *all* structs now? Is Widget supposed to be RCO (this is not stated clearly)? Similarly, in the next example about fun(exprA, exprB, exprC) it's not clear exactly which parameter is supposed to be RCO. I can guess, but it's better to be 100% unambiguous. Then the rule that states that opAddRef and opRelease are not issued for 'this': is this safe from race conditions? E.g., if I'm inside a method and somebody outside calls opRelease and frees the object 'this' points to. Or are we assuming that RCOs must be thread-local? If so, this should be stated explicitly. Under "Relinquishing an owned resource":The method is correctly not annotated with return because the slice it returns is not scoped by this. Note that if the implementer of Widget forgets the assignment _payload = null, user code may end up with a dangling reference.So basically such a method cannot be marked safe, right? T -- Only boring people get bored. -- JM
Feb 26 2015
On 27/02/2015 10:50 a.m., Andrei Alexandrescu wrote:http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. Thanks, AndreiEither I missed something or: If I go new a type like: Widget widget = new Widget(); This would still use the GC to allocate the memory + emplace it. Even if it contains the two special RC functions. Also what about properties? What if one of them may or may not be RC'd. Should there be a conditional call to the GC to add it to be scanned on assignment? Anyway, I think it is mostly there.
Feb 26 2015
On 2/26/15 5:28 PM, Rikki Cattermole wrote:On 27/02/2015 10:50 a.m., Andrei Alexandrescu wrote:Yah, DIP74 is intentionally very "policy up, implementation down". It completely leaves the allocation mechanism to user code. See e.g. this excerpt: "Usually such approaches also use private constructors and object factories to ensure the same allocation method is used during creation and destruction of the object."http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. Thanks, AndreiEither I missed something or: If I go new a type like: Widget widget = new Widget(); This would still use the GC to allocate the memory + emplace it. Even if it contains the two special RC functions.Also what about properties? What if one of them may or may not be RC'd. Should there be a conditional call to the GC to add it to be scanned on assignment?I don't understand this. Members compose naturally. Andrei
Feb 26 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, AndreiP.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.
Feb 26 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:hadn't*, Sorry.http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. Thanks, AndreiP.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
Feb 26 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
Feb 26 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
Mar 01 2015
On Sunday, 1 March 2015 at 13:13:58 UTC, bearophile wrote:Jacob Carlborg: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. :Darc 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
Mar 02 2015
On 2015-02-26 22:50, Andrei Alexandrescu wrote:http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss.To me this looks like ARC (Automated Reference Counting). I know that Walter has several complains about ARC, like he wrote in another thread [1]: "RC has further performance and code bloat problems when used with exception handling" Is that dealt with or is it something one just have to accepted when using reference counting? [1] http://forum.dlang.org/post/mcbejn$2tao$1 digitalmars.com -- /Jacob Carlborg
Feb 26 2015
Andrei Alexandrescu wrote:http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. Thanks, AndreiTrivial 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'. 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). 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
Feb 27 2015
On 2/27/15 1:09 AM, ted wrote:Andrei Alexandrescu wrote:Fixed, thanks!http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. Thanks, AndreiTrivial 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'.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 objectThis is tricky. I meant to discuss it; for now I planted a TODO. Andrei
Feb 27 2015
On 2/27/15 9:09 AM, Andrei Alexandrescu wrote:On 2/27/15 1:09 AM, ted wrote:Wouldn't you bless this mechanism of logical const the same way synchronized does? -SteveProbably 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 objectThis is tricky. I meant to discuss it; for now I planted a TODO.
Feb 27 2015
On 2/27/15 6:46 AM, Steven Schveighoffer wrote:On 2/27/15 9:09 AM, Andrei Alexandrescu wrote:Yes, it's a similar matter. -- AndreiOn 2/27/15 1:09 AM, ted wrote:Wouldn't you bless this mechanism of logical const the same way synchronized does?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 objectThis is tricky. I meant to discuss it; for now I planted a TODO.
Feb 27 2015
Andrei Alexandrescu wrote:On 2/27/15 1:09 AM, ted wrote:I'm still a bit confused here: the examples in DIP74 showed the freeing of memory via 'GC.free(cast(void*) this);' - so I had assumed that 'Widget a = new Widget' would be the way it was created? (and that automatically uses GC - or is this what I am missing?) I can see how a system that used (for example) malloc/calloc/free would work, I'm just querying the consistency of the examples within DIP74?Andrei Alexandrescu wrote:Fixed, thanks!http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. Thanks, AndreiTrivial 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'.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 objectThis is tricky. I meant to discuss it; for now I planted a TODO. Andrei
Feb 27 2015
On Friday, 27 February 2015 at 22:03:06 UTC, ted wrote:I can see how a system that used (for example) malloc/calloc/free would work, I'm just querying the consistency of the examples within DIP74?That is on of the 2 main problems with this DIP. The memory management of the object is linked to its memory management, which will force a ton a code duplication. The second problem is that we are coming up with a myriad of ad hoc solutions for various aspect of the same problem, with no visibility on what the whole thing is going to look like (so there is no base to compare the current road we are taking to any alternative proposal, deemed too complex).
Feb 27 2015
On 2/27/15 2:03 PM, ted wrote:I'm still a bit confused here: the examples in DIP74 showed the freeing of memory via 'GC.free(cast(void*) this);' - so I had assumed that 'Widget a = new Widget' would be the way it was created? (and that automatically uses GC - or is this what I am missing?)The GC allows both manual freeing and via tracing. So after allocating with new, a user may either leave it to the GC or call the destructor followed by GC.free.I can see how a system that used (for example) malloc/calloc/free would work, I'm just querying the consistency of the examples within DIP74?GC.malloc/GC.free and malloc/free should both work. Adnrei
Feb 27 2015
From the perspective of someone mostly indifferent to the support for it: Why does DIP74 require the references to be counted on assignment? Shouldn't it be defined such that reference counting operations only need to occur when an unbalanced or escapable reference is created? This would eliminate a large number of the required references. As long as the reference count of an object is the same entering a function as when it leaves the function, there's no need to do a bunch of twiddling in the middle. It also appears to me that the opAddRef in the examples is simpler than it should be. I believe it should be doing an `assert(_refs)` first, to ensure a valid state entering into the function. Lastly, I believe it should be opReleaseRef rather than opRelease, simply to be explicit on what is being released.
Feb 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.Destroy: The scheme is too simplistic. You need to add "policy" as a template parameter to retain/release so that you can support different ownership schemes with strong typing (compile time). You also need a policy-link between the receiver and the object. The DIP needs to prove that the protocol can be used to efficiently implement the following in various configurations: - weak-references with zeroing - auto release pools - unique ownership - optional locking and transfer between threads - wrapping of foreign objects that have their own RC scheme
Feb 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, AndreiIt'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?
Feb 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/
Feb 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, AndreiI'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...
Feb 27 2015
On 2/27/15 7:17 AM, Manu via Digitalmars-d wrote: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.Yah. I've added a TODO.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.Structs don't get any special treatment with DIP74, only classes and interfaces.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?That might be a future improvement. In fact that may be possible today; I've spoken to an ARC expert who read DIP74 and said Apple's ARC does not insert a retain() for a function call, i.e. it assumes functions only borrow unless they actually do keep a pointer (e.g. assign to a member or global), and only in that case inserts a retain(). If I'm not missing something, we can do this with DIP74 which will reduce the opAddRef/opRelease traffic quite a bit.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...Yah, leave that to users. Andrei
Feb 27 2015
On 28 February 2015 at 01:43, Andrei Alexandrescu via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 2/27/15 7:17 AM, Manu via Digitalmars-d wrote:Well this is the case of the highest value to me, and DIP74 offers nothing? Can I call opAddRef/opRelease from within the postblit/destructor manually and expect the compiler to elide calls correctly? That doesn't seem foolproof though, and you also said manual calls are not safe. Why not specify a call sequence?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.Structs don't get any special treatment with DIP74, only classes and interfaces.Hmmm, that does sound right. Very nice.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?That might be a future improvement. In fact that may be possible today; I've spoken to an ARC expert who read DIP74 and said Apple's ARC does not insert a retain() for a function call, i.e. it assumes functions only borrow unless they actually do keep a pointer (e.g. assign to a member or global), and only in that case inserts a retain(). If I'm not missing something, we can do this with DIP74 which will reduce the opAddRef/opRelease traffic quite a bit.
Feb 27 2015
On 2/27/15 7:52 AM, Manu via Digitalmars-d wrote:Well this is the case of the highest value to me, and DIP74 offers nothing?For structs you use postblit and destructors. -- Andrei
Feb 27 2015
On 28 February 2015 at 02:00, Andrei Alexandrescu via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 2/27/15 7:52 AM, Manu via Digitalmars-d wrote:That doesn't work now, and I don't see why that would suddenly work under DIP74?Well this is the case of the highest value to me, and DIP74 offers nothing?For structs you use postblit and destructors. -- Andrei
Feb 28 2015
On 2/28/15 5:43 PM, Manu via Digitalmars-d wrote:On 28 February 2015 at 02:00, Andrei Alexandrescu via Digitalmars-d <digitalmars-d puremagic.com> wrote:Per DIP25 and RCSlice, you may define a safe struct with reference counting that owns resources. -- AndreiOn 2/27/15 7:52 AM, Manu via Digitalmars-d wrote:That doesn't work now, and I don't see why that would suddenly work under DIP74?Well this is the case of the highest value to me, and DIP74 offers nothing?For structs you use postblit and destructors. -- Andrei
Feb 28 2015
On 2/27/15 7:52 AM, Manu via Digitalmars-d wrote:Can I call opAddRef/opRelease from within the postblit/destructor manually and expect the compiler to elide calls correctly? That doesn't seem foolproof though, and you also said manual calls are not safe. Why not specify a call sequence?Ah, I think you mean structs that have a class member? The compiler will insert opAddRef and opRelease appropriately: ========= * struct, class, and closure types that have RCO members accommodate calls to opRelease during their destruction. ========= Andrei
Feb 27 2015
On 28 February 2015 at 02:02, Andrei Alexandrescu via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 2/27/15 7:52 AM, Manu via Digitalmars-d wrote:Well, not specifically. I mean any struct that has any indirect member(/s). The point of a struct is that the layout is entirely at user discretion, and I may want to pass some small RC aggregate by value. 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. It's at my discretion what the contents of my struct is (in most of my cases, just pointers to opaque types, but not classes). If that's not practical (for instance, because classes assign by reference, but struc opAssign may do anything), then we should be able to call inc/dec ref manually, and have them optimise correctly? But that sounds like much more trouble to me.Can I call opAddRef/opRelease from within the postblit/destructor manually and expect the compiler to elide calls correctly? That doesn't seem foolproof though, and you also said manual calls are not safe. Why not specify a call sequence?Ah, I think you mean structs that have a class member? The compiler will insert opAddRef and opRelease appropriately:========= * struct, class, and closure types that have RCO members accommodate calls to opRelease during their destruction. ========= Andrei
Feb 28 2015
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
Feb 28 2015
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:*sigh* ... ever, or in DIP74? 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); } } X is a struct, not a class. If DIP74 can't do this efficiently, then it's no use to me. Do I need to abuse the type system by declaring: class Opaque { void opInc() { inc(cast(void*)this); } void opDec() { dec(cast(void*)this); } } That's a really lame thing to do. Debuggers will dereference Y, try and present a vtable and stuff to me. In the event I want to mirror the opaque C struct definition on the D side, I can't express it because class has implicit members which aren't actually there. What is the resistance to making it work on struct? It just seems like another arbitrary edge case in the language.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
Feb 28 2015
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:In the foreseeable future.On 2/28/15 5:43 PM, Manu via Digitalmars-d wrote:*sigh* ... ever, or in DIP74?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. -- AndreiI 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); } } Andrei
Feb 28 2015
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:You've conveniently ignored the word 'efficient'. Okay, so if I'm not better off then I've always been, what is the good of DIP74 to me?On 1 March 2015 at 12:21, Andrei Alexandrescu via Digitalmars-d <digitalmars-d puremagic.com> wrote:In the foreseeable future.On 2/28/15 5:43 PM, Manu via Digitalmars-d wrote:*sigh* ... ever, or in DIP74?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. -- AndreiI 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); } }
Feb 28 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: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.On 2/28/15 6:49 PM, Manu via Digitalmars-d wrote:You've conveniently ignored the word 'efficient'.On 1 March 2015 at 12:21, Andrei Alexandrescu via Digitalmars-d <digitalmars-d puremagic.com> wrote:In the foreseeable future.On 2/28/15 5:43 PM, Manu via Digitalmars-d wrote:*sigh* ... ever, or in DIP74?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. -- AndreiI 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); } }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
Feb 28 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: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.On 1 March 2015 at 12:51, 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.On 2/28/15 6:49 PM, Manu via Digitalmars-d wrote:You've conveniently ignored the word 'efficient'.On 1 March 2015 at 12:21, Andrei Alexandrescu via Digitalmars-d <digitalmars-d puremagic.com> wrote:In the foreseeable future.On 2/28/15 5:43 PM, Manu via Digitalmars-d wrote:*sigh* ... ever, or in DIP74?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. -- AndreiI 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); } }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.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".
Feb 28 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: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.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.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. AndreiThat 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.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".
Feb 28 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. AndreiYes please. I'd be very interested in hearing any thoughts you have on this.
Mar 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: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(); } AndreiIt might be more productive to look into improvements of optimizations related to copying objects. AndreiYes please. I'd be very interested in hearing any thoughts you have on this.
Mar 01 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, AndreiLGTM, it is great to see something done for deterministic class destruction. It's unclear to me if an RCO object is a subtype of the corresponding class or the reverse or none.
Feb 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, AndreiopAddRef/opRelease breaks SOLID's single responsibility principle.
Mar 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, AndreiWith 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.
Mar 03 2015
On 3/3/15 12:53 AM, Volodymyr wrote:On Thursday, 26 February 2015 at 21:50:56 UTC, Andrei Alexandrescu wrote:Correct. That's a tactical matter that can be addressed e.g. with mixin templates.http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. Thanks, AndreiWith 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.We couldn't make that work with safety. Andrei
Mar 03 2015
On Tuesday, 3 March 2015 at 09:58:12 UTC, Andrei Alexandrescu wrote:On 3/3/15 12:53 AM, Volodymyr wrote:Why couldn't? Let's for all return (this) functions make wrappers that rerturn RefCounter!MemberType(member, ownerCounterPtr), and same thing for public fields The wrapper nedded only for realy owned resources (but not simple gc's refs).On Thursday, 26 February 2015 at 21:50:56 UTC, Andrei Alexandrescu wrote:Correct. That's a tactical matter that can be addressed e.g. with mixin templates.http://wiki.dlang.org/DIP74 got to reviewable form. Please destroy and discuss. Thanks, AndreiWith 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.We couldn't make that work with safety. Andrei
Mar 04 2015
Implicit conversion to supertypes (class or interface) is allowed ONLY if the supertype is also a reference counted type. It follows that reference counted types cannot be converted to Object (unless Object itself defines the two methods). But how about calling methods of supertypes? class Basic { Basic castToBasic() return { return this; } } class RCWidged : Basic { void opAddRef(); void opRelease(); // etc } Object a; { auto b = RCWidget; a = b.castToBasic; // unsafe? opAddReff? // b.opRelease? } a < new RCWidget // call to Object.opCmp. Error? The problem with shared_ptr-like solution - "this" parameter is not shared_ptr. You try to build shared_ptr into "this". But basic class knows nothing about RC in child class. And those who use the basic class know nothing. RefCounter is unsafe and mutable. Let's do it universal (for classes/value structs/ and unions), add method auto opShareResource(T)(ref T t) to handle parts of RC class that go away. auto opShareResource(T)(ref T t) { return RefCounter!T(t, ownerRefCounter); } this method will be called for direct or indirect access to fields of RCClass and may wrap resource or throw or do anything else.
Mar 04 2015
On 3/4/15 5:08 AM, Volodymyr wrote:Implicit conversion to supertypes (class or interface) is allowed ONLY if the supertype is also a reference counted type. It follows that reference counted types cannot be converted to Object (unless Object itself defines the two methods). But how about calling methods of supertypes?That also entails an implicit conversion. To clarify, I added this to http://wiki.dlang.org/DIP74#General: "Method calls to supertypes are only allowed if the supertype that defines the method is also reference counted." Andrei
Mar 04 2015
After looking at DIP74, it seems that there is no way to create a weak reference to a ref counted object, but is not explicitly stated. Has this idea been considered at all?
Mar 04 2015
On 3/4/15 10:48 AM, bitwise wrote:After looking at DIP74, it seems that there is no way to create a weak reference to a ref counted object, but is not explicitly stated. Has this idea been considered at all?DIP74 aims at not disallowing weak references whilst leaving it to libraries to effect implementations, but we'd need a proof of concept implementation to make sure DIP74 is enough as is. -- Andrei
Mar 04 2015
On Wednesday, 4 March 2015 at 18:59:54 UTC, Andrei Alexandrescu wrote:On 3/4/15 10:48 AM, bitwise wrote:I suppose you could add "getWeak()" and "releaseWeak()" to a ref counted class, and implement a "struct Weak(T)" that calls them for you, but I doesn't seem like much of a leap to just add something like this to the DIP. couldn't "opAddWeak" and "opReleaseWeak" be added and follow identical rules to "opAddRef" and "opRelease"? The compiler could simply insert "opAddWeak() instead of opAddRef() when it found the "weak" keyword. For example: class Widget { private uint _refs = 1; private uint _weaks = 0; private int[] _payload; // owned void opAddRef() { ++_refs; } void opRelease() { if (--_refs == 0) { GC.free(_payload.ptr); _payload = null; // I'm assuming this would leave "_weaks" and "_refs" untouched this.destroy(); if(_weaks == 0) { GC.free(cast(void*)this); } } } void opAddWeak() { ++_weaks; } void opReleaseWeak() { if(--_weaks == 0 && _refs == 0) { GC.free(cast(void*)this); } } // optional/recommended bool expired() { return _refs == 0; } } Widget a = new Widget; // refs == 1, weaks == 0 Widget b = weak a; // refs == 1, weaks == 1 //a.opAddWeak(); Widget c = b; // b.opAddRef(); // refs == 2, weaks == 1 a = null; // refs == 1, weaks == 1 //a.opRelease(); assert(b.expired() == false); c = null; // refs == 0, weaks == 1 // c.opRelease(); assert(b.expired() == true); b = null; // refs == 0, weaks == 0 // b.opReleaseWeak(); ////////// or for function calls: void func(weak Widget a) { //... } Widget a = new Widget; func(a);After looking at DIP74, it seems that there is no way to create a weak reference to a ref counted object, but is not explicitly stated. Has this idea been considered at all?DIP74 aims at not disallowing weak references whilst leaving it to libraries to effect implementations, but we'd need a proof of concept implementation to make sure DIP74 is enough as is. -- Andrei
Mar 04 2015
On 3/4/15 12:04 PM, bitwise wrote:I suppose you could add "getWeak()" and "releaseWeak()" to a ref counted classMy initial attempt would be to see if opAddRef and opRelease defined by a distinct weak pointer type would work. -- Andrei
Mar 04 2015