Re: I have made a discovery
On Saturday, 18 April 2015 at 15:24:27 UTC, w0rp wrote: The following code almost compiles. import core.stdc.stdlib; class Foo : Exception { @nogc pure nothrow @safe this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) { super(msg, file, line, next); } @nogc new(size_t size) { return malloc(size); } } @nogc void main() { throw new Foo(Oh no!); } That's right. An unofficially deprecated feature of the language and a newer feature of the language coming together in an interesting way. The only thing stopping this code from actually working is a trivial change to druntime to mark the Throwable, Exception, and Error constructors as @nogc, which I just created a pull request for directly through GitHub. https://github.com/D-Programming-Language/druntime/pull/1223 Now imagine that instead of just a malloc which leaks memory like the above, other allocation schemes are used here instead. Consider also the coming addition to the language for class reference counting methods opAddRef and opRelease. Then let your imagination run wild. Enjoy! I don't see anything interesting here. Controlling allocation was never the issue (MyException.create ftw). It is deallocation that matters.
Re: I have made a discovery
On Saturday, 18 April 2015 at 15:24:27 UTC, w0rp wrote: @nogc void main() { throw new Foo(Oh no!); } Though until https://issues.dlang.org/show_bug.cgi?id=14119 is resolved the tracehandler GC allocates anyhow. Why are malloc exceptions better then gc exceptions? Are you throwing so many of them that the GC becomes a bottleneck :)?
Re: I have made a discovery
On Tue, 21 Apr 2015 22:53:15 +, Martin Nowak wrote: On Saturday, 18 April 2015 at 15:24:27 UTC, w0rp wrote: @nogc void main() { throw new Foo(Oh no!); } Though until https://issues.dlang.org/show_bug.cgi?id=14119 is resolved the tracehandler GC allocates anyhow. Why are malloc exceptions better then gc exceptions? Are you throwing so many of them that the GC becomes a bottleneck :)? the idea is to avoid allocations alltogether. malloc is a sample, one can use statically allocated pool instead, for example. this way functions can throw, yet still be @nogc. signature.asc Description: PGP signature
Re: I have made a discovery
On Sunday, 19 April 2015 at 02:50:59 UTC, Rikki Cattermole wrote: So I went with closest I thought it was to make the point. I don't understand what the point is... is it just syntax?
Re: I have made a discovery
On Sunday, 19 April 2015 at 09:57:52 UTC, w0rp wrote: The interesting thing about this is that 'throw new ExceptionType(...)' could be reference counted. The downside of What's wrong with just putting exceptions in a dedicated memory area like C++?
Re: I have made a discovery
The interesting thing about this is that 'throw new ExceptionType(...)' could be reference counted. The downside of not getting rid of the 'new' overloading at some point is that it can make the operator do surprising and unexpected things, so the rationale for getting rid of it is similar to the rationale behind disallowing overloading of '' and '||'. What I found more interesting is that class constructors themselves can be marked @nogc, which I never thought to do before. So whatever syntax we end up with for 'allocate with this other allocator and call this constructor' could take advantage of that. I'm not sure how that will end up looking in the end, but I am reminded of Objective C again, where allocation and construction are explicitly separated. // Enough time in Wonderland makes this seem perfectly natural. MyClass* foo = [[MyClass alloc] initWithNumber:3];
Re: I have made a discovery
On 19/04/2015 11:48 p.m., Adam D. Ruppe wrote: On Sunday, 19 April 2015 at 02:50:59 UTC, Rikki Cattermole wrote: So I went with closest I thought it was to make the point. I don't understand what the point is... is it just syntax? I was just toying with different syntax's regarding allocation. Atleast to me, none of them really fit.
Re: I have made a discovery
On Saturday, 18 April 2015 at 15:24:27 UTC, w0rp wrote: Consider also the coming addition to the language for class reference counting methods opAddRef and opRelease. Since it's classes we are talking about, wouldn't that mean we need to do a virtual function call each time a class reference gets assigned or goes out of scope(and twice when it gets reassigned)?
Re: I have made a discovery
On 2015-04-19 11:57, w0rp wrote: I'm not sure how that will end up looking in the end, but I am reminded of Objective C again, where allocation and construction are explicitly separated. // Enough time in Wonderland makes this seem perfectly natural. MyClass* foo = [[MyClass alloc] initWithNumber:3]; And in Swift they removed then need to call alloc. -- /Jacob Carlborg
Re: I have made a discovery
I *think* my PR might have also led me to discovering some kind of DMD bug to do with not being able to call a @nogc super class constructor from a constructor which isn't @nogc. It could be something else entirely, but it caused some undefined reference bugs to appear, which is odd.
Re: I have made a discovery
On Saturday, 18 April 2015 at 15:39:05 UTC, w0rp wrote: I *think* my PR might have also led me to discovering some kind of DMD bug to do with not being able to call a @nogc super class constructor from a constructor which isn't @nogc. It could be something else entirely, but it caused some undefined reference bugs to appear, which is odd. Disregard that, I needed to change the .di file too...
Re: I have made a discovery
On Sun, 19 Apr 2015 12:29:45 +1200, Rikki Cattermole wrote: Awesome! Although we may need to undeprecate that feature. as it is not generating deprecation warning now, it should be fairly easy: just reintroduce it into specs. i can see why it was deprecated in the first place, but it's much easier to simply write new Exception instead of allocateWithMyCoolScheme!Exception. signature.asc Description: PGP signature
Re: I have made a discovery
On Sunday, 19 April 2015 at 00:39:03 UTC, ketmar wrote: On Sun, 19 Apr 2015 12:29:45 +1200, Rikki Cattermole wrote: Awesome! Although we may need to undeprecate that feature. as it is not generating deprecation warning now, it should be fairly easy: just reintroduce it into specs. i can see why it was deprecated in the first place, but it's much easier to simply write new Exception instead of allocateWithMyCoolScheme!Exception. maybe I'm dumb in asking this, but if there was already an API for allocators in D... why is a std.allocator not being written ontop of it? it seems much more elegant to begin with.
Re: I have made a discovery
On Sunday, 19 April 2015 at 00:39:03 UTC, ketmar wrote: On Sun, 19 Apr 2015 12:29:45 +1200, Rikki Cattermole wrote: Awesome! Although we may need to undeprecate that feature. as it is not generating deprecation warning now, it should be fairly easy: just reintroduce it into specs. i can see why it was deprecated in the first place, but it's much easier to simply write new Exception instead of allocateWithMyCoolScheme!Exception. If you overload a class's `new`, you are deciding for your class's user how it will be allocated. I think it's better to let the programmer decide how they want the class to be allocated.
Re: I have made a discovery
On Sun, 19 Apr 2015 00:50:23 +, weaselcat wrote: maybe I'm dumb in asking this, but if there was already an API for allocators in D... why is a std.allocator not being written ontop of it? it seems much more elegant to begin with. ability to override `new` and `delete` is a big can of worms. c++ got into that, and now it's not recommended to touch that operators. in a short: it's inflexible (you can't use two different `new` with one class, for example -- if not count the weirdo `new(5) A()` and such), you can't predict how your class will be allocated (yea, you didn't define `new` for your class... but one of it's parents did and... bam!) and so on. so i fully understand why it's silently deprecated. yet i still don't want it to go. ;-) signature.asc Description: PGP signature
Re: I have made a discovery
On Sun, 19 Apr 2015 01:53:41 +, Adam D. Ruppe wrote: On Sunday, 19 April 2015 at 00:39:03 UTC, ketmar wrote: but it's much easier to simply write new Exception instead of allocateWithMyCoolScheme!Exception. eh i would just call it New!Exception where the cool scheme is in the module name. So you import mycoolscheme; which defines the New. Then you can disambiguate with the usual module features if you use two schemes in the same scope. It'd be so beautiful. ah, i keep forgetting about D ability to rename imports and detect name conflicts. too much delphi in my youth. ;-) signature.asc Description: PGP signature
Re: I have made a discovery
On Sunday, 19 April 2015 at 02:24:06 UTC, Rikki Cattermole wrote: int[3] values = allocate!(int[3]); Why would you ever do that? int[3] is statically allocated auto values = allocate!(int[])(3); would make a lot more sense, then values would be typed perhaps to int[], but also it might be typed to something like RefCounted!(int[]) or Unique!(int[]) or something, so the requirement to deallocate is encoded right there in the type and thus known to the compiler. But even `int[] values = new!(int[])(3);` is very similar to the built-in syntax and can do exactly the same thing - while also being changeable to a new scheme by importing a different module.
Re: I have made a discovery
On Sun, 19 Apr 2015 01:19:46 +, Brian Schott wrote: On Sunday, 19 April 2015 at 00:39:03 UTC, ketmar wrote: On Sun, 19 Apr 2015 12:29:45 +1200, Rikki Cattermole wrote: Awesome! Although we may need to undeprecate that feature. as it is not generating deprecation warning now, it should be fairly easy: just reintroduce it into specs. i can see why it was deprecated in the first place, but it's much easier to simply write new Exception instead of allocateWithMyCoolScheme!Exception. If you overload a class's `new`, you are deciding for your class's user how it will be allocated. I think it's better to let the programmer decide how they want the class to be allocated. yes, i know all that... but i still want it! ;-) signature.asc Description: PGP signature
Re: I have made a discovery
On 19/04/2015 3:24 a.m., w0rp wrote: The following code almost compiles. import core.stdc.stdlib; class Foo : Exception { @nogc pure nothrow @safe this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) { super(msg, file, line, next); } @nogc new(size_t size) { return malloc(size); } } @nogc void main() { throw new Foo(Oh no!); } That's right. An unofficially deprecated feature of the language and a newer feature of the language coming together in an interesting way. The only thing stopping this code from actually working is a trivial change to druntime to mark the Throwable, Exception, and Error constructors as @nogc, which I just created a pull request for directly through GitHub. https://github.com/D-Programming-Language/druntime/pull/1223 Now imagine that instead of just a malloc which leaks memory like the above, other allocation schemes are used here instead. Consider also the coming addition to the language for class reference counting methods opAddRef and opRelease. Then let your imagination run wild. Enjoy! Awesome! Although we may need to undeprecate that feature.
Re: I have made a discovery
On Sunday, 19 April 2015 at 00:39:03 UTC, ketmar wrote: but it's much easier to simply write new Exception instead of allocateWithMyCoolScheme!Exception. eh i would just call it New!Exception where the cool scheme is in the module name. So you import mycoolscheme; which defines the New. Then you can disambiguate with the usual module features if you use two schemes in the same scope. It'd be so beautiful.
Re: I have made a discovery
On Sunday, 19 April 2015 at 01:19:47 UTC, Brian Schott wrote: If you overload a class's `new`, you are deciding for your class's user how it will be allocated. Without telling them btw. (Well, except the documentation or the source.) So now, they new it and expect the GC to clean it up like any other class but that invisibly doesn't happen. Overriding new was totally a misfeature in D and it should go away. BTW having new in the language at all I wish wasn't a thing. Perhaps it was right back in old D1, but not ideal in D2, where we can easily define a template to do it - which could be easily swapped out at the usage point and enable all kinds of nice things. Of course, we can still define library New!T (and indeed, I think we should), but the keyword will always have a bit of a brainspace edge over it...
Re: I have made a discovery
On 19/04/2015 1:52 p.m., Adam D. Ruppe wrote: On Sunday, 19 April 2015 at 01:19:47 UTC, Brian Schott wrote: If you overload a class's `new`, you are deciding for your class's user how it will be allocated. Without telling them btw. (Well, except the documentation or the source.) So now, they new it and expect the GC to clean it up like any other class but that invisibly doesn't happen. Overriding new was totally a misfeature in D and it should go away. BTW having new in the language at all I wish wasn't a thing. Perhaps it was right back in old D1, but not ideal in D2, where we can easily define a template to do it - which could be easily swapped out at the usage point and enable all kinds of nice things. Of course, we can still define library New!T (and indeed, I think we should), but the keyword will always have a bit of a brainspace edge over it... auto adding(int x, int y) { int[3] values = allocate!(int[3]); values[0] = x; values[1] = y; values[2] = x + y; return values; } ... auto adding(int x, int y) { int[3] values = new!(int[3]); values[0] = x; values[1] = y; values[2] = x + y; return values; } ... auto adding(int x, int y) { int[3] values = new int[](3); values[0] = x; values[1] = y; values[2] = x + y; return values; } ... struct MyAllocator { T* opAllocate(T)(){ T* value; // alloc value.rtInfo.fromGC = false; value.rtInfo.isRefCounted = false; value.rtInfo.isGCFree = true; // allows GC to free it value.rtInfo.freeFunction = opFree; // maybe? return value; } void opFree(T)(T*){ // free } } new(MyAllocator): auto adding(int x, int y) { int[3] values = new int[](3); values[0] = x; values[1] = y; values[2] = x + y; return values; } ... I'm not totally sold.
Re: I have made a discovery
On 19/04/2015 2:45 p.m., Adam D. Ruppe wrote: On Sunday, 19 April 2015 at 02:24:06 UTC, Rikki Cattermole wrote: int[3] values = allocate!(int[3]); Why would you ever do that? int[3] is statically allocated auto values = allocate!(int[])(3); would make a lot more sense, then values would be typed perhaps to int[], but also it might be typed to something like RefCounted!(int[]) or Unique!(int[]) or something, so the requirement to deallocate is encoded right there in the type and thus known to the compiler. But even `int[] values = new!(int[])(3);` is very similar to the built-in syntax and can do exactly the same thing - while also being changeable to a new scheme by importing a different module. I couldn't fully remember the syntax. So I went with closest I thought it was to make the point.
Re: I have made a discovery
On 4/18/15 5:50 PM, weaselcat wrote: On Sunday, 19 April 2015 at 00:39:03 UTC, ketmar wrote: On Sun, 19 Apr 2015 12:29:45 +1200, Rikki Cattermole wrote: Awesome! Although we may need to undeprecate that feature. as it is not generating deprecation warning now, it should be fairly easy: just reintroduce it into specs. i can see why it was deprecated in the first place, but it's much easier to simply write new Exception instead of allocateWithMyCoolScheme!Exception. maybe I'm dumb in asking this, but if there was already an API for allocators in D... why is a std.allocator not being written ontop of it? it seems much more elegant to begin with. Nah, it's not. -- Andrei
Re: I have made a discovery
On Sunday, 19 April 2015 at 02:42:28 UTC, ketmar wrote: On Sun, 19 Apr 2015 00:50:23 +, weaselcat wrote: maybe I'm dumb in asking this, but if there was already an API for allocators in D... why is a std.allocator not being written ontop of it? it seems much more elegant to begin with. ability to override `new` and `delete` is a big can of worms. c++ got into that, and now it's not recommended to touch that operators. in a short: it's inflexible (you can't use two different `new` with one class, for example -- if not count the weirdo `new(5) A()` and such), you can't predict how your class will be allocated (yea, you didn't define `new` for your class... but one of it's parents did and... bam!) and so on. so i fully understand why it's silently deprecated. yet i still don't want it to go. ;-) I was unaware of how the override new worked, after reading the thread again it makes more sense why it's not used now. Thanks.