digitalmars.D - Herb Sutter on zero cost exceptions for C++
- shfit (4/4) Sep 26 2019 Herb Sutter gave a pretty interesting talk on zero cost
- rikki cattermole (5/11) Sep 26 2019 We have a solution.
- Dominikus Dittes Scherkl (4/8) Sep 27 2019 I thought it's because RefCount doesn't work without the changes
- a11e99z (3/13) Sep 27 2019 what is @life? (searching by forum gives only this message)
- Paulo Pinto (2/17) Sep 27 2019 https://dlang.org/blog/2019/07/15/ownership-and-borrowing-in-d/
- H. S. Teoh (36/40) Sep 27 2019 Thanks for the link! I've also been wondering, with all this talk about
- Timon Gehr (17/63) Sep 27 2019 Not impossible, you are just not supposed to do it. The proposal does
- H. S. Teoh (27/36) Sep 30 2019 [...]
- Jonathan Marler (3/18) Sep 27 2019 "Life explained as a video game"
- Timon Gehr (2/13) Sep 27 2019 (Nor with those changes.)
- Jonathan Marler (3/7) Sep 27 2019 Wow this is a really big deal. Zero-overhead exception with no
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (13/22) Sep 27 2019 Well, IIRC modern C++ does not do memory allocation today, it
- Manu (5/9) Sep 29 2019 If C++ does this, and we want to extern(C++), then we will support this....
- Johannes Pfau (59/73) Sep 29 2019 It's a very interesting idea. In the end, what he proposes is to bake
Herb Sutter gave a pretty interesting talk on zero cost exceptions and RTTI. https://m.youtube.com/watch?v=ARYP83yNAWk Could this be an option for D to avoid gc exceptions?
Sep 26 2019
On 27/09/2019 5:51 AM, shfit wrote:Herb Sutter gave a pretty interesting talk on zero cost exceptions and RTTI. https://m.youtube.com/watch?v=ARYP83yNAWk Could this be an option for D to avoid gc exceptions?We have a solution. https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1008.md I've looked at the dmd and Phobos PR's, I don't know what is currently holding it up from going live.
Sep 26 2019
On Thursday, 26 September 2019 at 18:09:08 UTC, rikki cattermole wrote:We have a solution. https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1008.md I've looked at the dmd and Phobos PR's, I don't know what is currently holding it up from going live.I thought it's because RefCount doesn't work without the changes from the life proposal.
Sep 27 2019
On Friday, 27 September 2019 at 07:53:56 UTC, Dominikus Dittes Scherkl wrote:On Thursday, 26 September 2019 at 18:09:08 UTC, rikki cattermole wrote:what is life? (searching by forum gives only this message)We have a solution. https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1008.md I've looked at the dmd and Phobos PR's, I don't know what is currently holding it up from going live.I thought it's because RefCount doesn't work without the changes from the life proposal.
Sep 27 2019
On Friday, 27 September 2019 at 09:36:33 UTC, a11e99z wrote:On Friday, 27 September 2019 at 07:53:56 UTC, Dominikus Dittes Scherkl wrote:https://dlang.org/blog/2019/07/15/ownership-and-borrowing-in-d/On Thursday, 26 September 2019 at 18:09:08 UTC, rikki cattermole wrote:what is life? (searching by forum gives only this message)We have a solution. https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1008.md I've looked at the dmd and Phobos PR's, I don't know what is currently holding it up from going live.I thought it's because RefCount doesn't work without the changes from the life proposal.
Sep 27 2019
On Fri, Sep 27, 2019 at 09:55:27AM +0000, Paulo Pinto via Digitalmars-d wrote:On Friday, 27 September 2019 at 09:36:33 UTC, a11e99z wrote:[...]Thanks for the link! I've also been wondering, with all this talk about live. One comment on the article, though: ownership as defined by Walter seems unnecessarily restrictive, in that it's impossible to have multiple mutable pointers to an object. Here's an enhancement based on an idea I had years ago: the concept of differentiating between "owning" pointers and "non-owning" pointers. An owning pointer is basically what Walter describes -- only a single such pointer can exist per object, and when that pointer goes out of the scope the object gets freed. Allocation functions like malloc() return an owning pointer. During its lifetime, however, any number of "non-owning" pointers can be made from it. A "non-owning" pointer cannot be passed to free() (or equivalent). In this scheme, free() only ever accepts an owning pointer. Furthermore, a non-owning pointer cannot outlive the scope of the owning pointer: they are 'scope', and their scope must be statically provable to be a subset of the scope of the owning pointer they are borrowing from. There is no need to restrict them with regards to mutability, however. This system can be implemented using RAII: pointers returned from memory allocators like malloc() are wrapped in an OwnerPtr struct that frees the pointer once it goes out of scope. It overrides assignment and copy ctors such that an OwnerPtr becomes null after it gets copied to another OwnerPtr (it has move semantics, and disables copy). An OwnerPtr can be copied into a regular pointer, under the condition that the regular pointer is scope (it cannot outlive the OwnerPtr itself). I used to actually use this scheme for memory management back when I was writing C/C++ code, and it works fairly well: only back then I didn't have 'scope' so there was the danger of a non-owning pointer leaking out and becoming a dangling pointer. With D's scope, this becomes a waterproof scheme AFAICT. T -- Never ascribe to malice that which is adequately explained by incompetence. -- Napoleon Bonapartewhat is life? (searching by forum gives only this message)https://dlang.org/blog/2019/07/15/ownership-and-borrowing-in-d/
Sep 27 2019
On 27.09.19 18:40, H. S. Teoh wrote:On Fri, Sep 27, 2019 at 09:55:27AM +0000, Paulo Pinto via Digitalmars-d wrote:Not impossible, you are just not supposed to do it. The proposal does zero checking at the safe/ live interface, which means it's by convention. live in the best case does nothing at all and in the worst case rips holes into safe instead of closing them.On Friday, 27 September 2019 at 09:36:33 UTC, a11e99z wrote:[...]Thanks for the link! I've also been wondering, with all this talk about live. One comment on the article, though: ownership as defined by Walter seems unnecessarily restrictive, in that it's impossible to have multiple mutable pointers to an object.what is life? (searching by forum gives only this message)https://dlang.org/blog/2019/07/15/ownership-and-borrowing-in-d/Here's an enhancement based on an idea I had years ago: the concept of differentiating between "owning" pointers and "non-owning" pointers. ...Yes, that's much better than a function attribute, but owning pointers don't need to be a built-in language concept. (See Rust.)An owning pointer is basically what Walter describes -- only a single such pointer can exist per object, and when that pointer goes out of the scope the object gets freed. Allocation functions like malloc() return an owning pointer. During its lifetime, however, any number of "non-owning" pointers can be made from it. ...That's what's called borrowing in Rust, but you need to be careful.A "non-owning" pointer cannot be passed to free() (or equivalent).Issue is you can have a non-owning pointer pointing to a data structure that contains owning pointers.In this scheme, free() only ever accepts an owning pointer. Furthermore, a non-owning pointer cannot outlive the scope of the owning pointer: they are 'scope', and their scope must be statically provable to be a subset of the scope of the owning pointer they are borrowing from. There is no need to restrict them with regards to mutability, however. ...Agreed.This system can be implemented using RAII: pointers returned from memory allocators like malloc() are wrapped in an OwnerPtr struct that frees the pointer once it goes out of scope. It overrides assignment and copy ctors such that an OwnerPtr becomes null after it gets copied to another OwnerPtr (it has move semantics, and disables copy). An OwnerPtr can be copied into a regular pointer, under the condition that the regular pointer is scope (it cannot outlive the OwnerPtr itself). ...As mentioned above this works if you have only one level of indirection.I used to actually use this scheme for memory management back when I was writing C/C++ code, and it works fairly well: only back then I didn't have 'scope' so there was the danger of a non-owning pointer leaking out and becoming a dangling pointer. With D's scope, this becomes a waterproof scheme AFAICT.Not really. E.g., you can have two non-owning pointers to a Array!int and then one of them reassigns the array, while the other borrowed a pointer to one of its elements. Rust enforces no mutable aliasing exactly because reassigning something may cause the old value to be deallocated.
Sep 27 2019
On Fri, Sep 27, 2019 at 07:13:36PM +0200, Timon Gehr via Digitalmars-d wrote: [...][...]A "non-owning" pointer cannot be passed to free() (or equivalent).Issue is you can have a non-owning pointer pointing to a data structure that contains owning pointers.[...] E.g., you can have two non-owning pointers to a Array!int and then one of them reassigns the array, while the other borrowed a pointer to one of its elements.Could you give a specific example with pseudocode? I'm having trouble understanding exactly what goes wrong here. I got as far as: struct S { OwnerPtr!int value; } OwnerPtr!S s = allocate!S(); S* s1 = s; // borrow S* s2 = s; // borrow int* elem = s1.value; // borrow from contained owning ptr s2.value = new OwnerPtr!int(123); // invalidates elem Doesn't this just mean that non-ownership should be transitive? I.e., if you have a non-owning pointer to some data structure, then all OwnerPtr's in the data structure effectively become non-owned from your POV, so reassigning is illegal.Rust enforces no mutable aliasing exactly because reassigning something may cause the old value to be deallocated.Doesn't that just mean that the borrowed pointer had a lifetime that exceeded the lifetime of the owning pointer? Therefore, it was (retroactively) illegal to have borrowed that pointer in the first place, since you couldn't guarantee that the owning pointer wouldn't become invalidated. Transitive non-ownership seems to be one way of dealing with this (though I'm not sure whether it's sufficient, or even consistent -- have to think about this more). T -- I am not young enough to know everything. -- Oscar Wilde
Sep 30 2019
On Friday, 27 September 2019 at 09:36:33 UTC, a11e99z wrote:On Friday, 27 September 2019 at 07:53:56 UTC, Dominikus Dittes Scherkl wrote:"Life explained as a video game" https://www.youtube.com/watch?v=ryFjCxGfqeEOn Thursday, 26 September 2019 at 18:09:08 UTC, rikki cattermole wrote:what is life? (searching by forum gives only this message)We have a solution. https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1008.md I've looked at the dmd and Phobos PR's, I don't know what is currently holding it up from going live.I thought it's because RefCount doesn't work without the changes from the life proposal.
Sep 27 2019
On 27.09.19 09:53, Dominikus Dittes Scherkl wrote:On Thursday, 26 September 2019 at 18:09:08 UTC, rikki cattermole wrote:(Nor with those changes.)We have a solution. https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1008.md I've looked at the dmd and Phobos PR's, I don't know what is currently holding it up from going live.I thought it's because RefCount doesn't work without the changes from the life proposal.
Sep 27 2019
On Thursday, 26 September 2019 at 17:51:16 UTC, shfit wrote:Herb Sutter gave a pretty interesting talk on zero cost exceptions and RTTI. https://m.youtube.com/watch?v=ARYP83yNAWk Could this be an option for D to avoid gc exceptions?Wow this is a really big deal. Zero-overhead exception with no memory allocation. Could be a big feature for D.
Sep 27 2019
On Friday, 27 September 2019 at 17:26:02 UTC, Jonathan Marler wrote:On Thursday, 26 September 2019 at 17:51:16 UTC, shfit wrote:Well, IIRC modern C++ does not do memory allocation today, it uses a preallocated buffer. What he is talking about is replicating Rust-style "Optional" union return values as throw/catch but implemented in registers only. So it is basically about reducing the amount of state that is transferred to the caller from the exception location with some hints of the implementation. For D this will be difficult because D provides the exception chain. I suggested register based throwing for D many years ago. Nothing new...Herb Sutter gave a pretty interesting talk on zero cost exceptions and RTTI. https://m.youtube.com/watch?v=ARYP83yNAWk Could this be an option for D to avoid gc exceptions?Wow this is a really big deal. Zero-overhead exception with no memory allocation. Could be a big feature for D.
Sep 27 2019
On Thu, Sep 26, 2019 at 10:55 AM shfit via Digitalmars-d <digitalmars-d puremagic.com> wrote:Herb Sutter gave a pretty interesting talk on zero cost exceptions and RTTI. https://m.youtube.com/watch?v=ARYP83yNAWk Could this be an option for D to avoid gc exceptions?If C++ does this, and we want to extern(C++), then we will support this... An interesting question might be if we are able to get ahead of the curve. I found his talk very motivating.
Sep 29 2019
Am Sun, 29 Sep 2019 18:57:21 -0700 schrieb Manu:On Thu, Sep 26, 2019 at 10:55 AM shfit via Digitalmars-d <digitalmars-d puremagic.com> wrote:It's a very interesting idea. In the end, what he proposes is to bake support for error codes into the language, but in a way which resembles exception handling. I think reusing the return channel for error codes in a union-like way with the result value and a flag to discriminate is quite clever. However, compared to exceptions your still trading no CPU-overhead in the success case and lots of overhead in the failure case for a little overhead in success and a little overhead in failure (the compiler always has to check the flag after calling such a function, to propagate the error further). But I'd think this is not a large problem: Performance sensitive code probably doesn't use exceptions anyway, cause in most cases where you can't afford this little overhead in the success case, you probably can't afford the large overhead exceptions cause in the failure case either. But still, we'd need some kind of benchmarks in the end. I also like this idea a lot cause it makes exception-like error handling viable for betterC/ microcontroller environments. So for his idea 1, implementing error value in a return channel: We should really experiment with that in D. We also have the benefit of already having nothrow... For his idea 2&3 IIRC, we already have contracts and IIRC we already have a flag which simply aborts the application / calls the debugger on failure instead of throwing. Regarding handling / not handling OOM to make more code nothrow: Seems interesting, but I'd have to think about it more, how it relates to D. His idea 4, explicitly marking all calls which can throw in some way (try), seems to be something which should be easy to implement in D. It's probably 99% compatible with the current grammar, we just need to allow try without catch. (Not sure if we need try at expression level as well: `bool a = try foo();` vs `try bool a = foo();`) But it needs a DIP of course. I'm not sure about the RTTI part: The downcast optimization is clever, but it only works if you can do whole-program-optimization (i.e. statically linked). Of course in embedded, this is the default case, so it is important and useful. Still, you should also be able to just walk up vtables in a linked-list style. Then all RTTI you need is one field in the Vtable which always links to the parent vtable, and when casting, you do this: class Foo{} clas Bar: Foo{} cast(Bar)foo => auto vtbl = foo.vtbl; while (vtbl && vtbl != Bar.vtbl) vtbl = vtbl.parent(); if (vtbl) // cast sucessfull else // cast failed Which has very little overhead. The main drawback for hard-realtime is that the overhead is not bounded: It's O(n) where n is the inheritance depth of the runtime object (foo). In practice, you're probably walking 1-20 elements in a linked list, which should be fast. But you can't easily determine n statically, unless you know all possible types for foo. (C++ probably can't do this because of multiple inheritance. Thinking about this, we probably also get problems when we want to cast to parent interfaces this way...) -- JohannesHerb Sutter gave a pretty interesting talk on zero cost exceptions and RTTI. https://m.youtube.com/watch?v=ARYP83yNAWk Could this be an option for D to avoid gc exceptions?If C++ does this, and we want to extern(C++), then we will support this... An interesting question might be if we are able to get ahead of the curve. I found his talk very motivating.
Sep 29 2019