www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - I have made a discovery

reply "w0rp" <devw0rp gmail.com> writes:
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!
Apr 18 2015
next sibling parent reply "w0rp" <devw0rp gmail.com> writes:
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.
Apr 18 2015
parent "w0rp" <devw0rp gmail.com> writes:
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...
Apr 18 2015
prev sibling next sibling parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
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.
Apr 18 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
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=20 easy: just reintroduce it into specs. i can see why it was deprecated in=20 the first place, but it's much easier to simply write "new Exception"=20 instead of "allocateWithMyCoolScheme!Exception".=
Apr 18 2015
next sibling parent reply "weaselcat" <weaselcat gmail.com> writes:
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.
Apr 18 2015
next sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Sun, 19 Apr 2015 00:50:23 +0000, 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=20 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=20 class, for example -- if not count the weirdo `new(5) A()` and such), you=20 can't predict how your class will be allocated (yea, you didn't define=20 `new` for your class... but one of it's parents did and... bam!) and so=20 on. so i fully understand why it's silently deprecated. yet i still don't=20 want it to go. ;-)=
Apr 18 2015
parent "weaselcat" <weaselcat gmail.com> writes:
On Sunday, 19 April 2015 at 02:42:28 UTC, ketmar wrote:
 On Sun, 19 Apr 2015 00:50:23 +0000, 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.
Apr 18 2015
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
Apr 18 2015
prev sibling next sibling parent reply "Brian Schott" <briancschott gmail.com> writes:
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.
Apr 18 2015
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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...
Apr 18 2015
parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
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.
Apr 18 2015
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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.
Apr 18 2015
parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
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.
Apr 18 2015
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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?
Apr 19 2015
parent Rikki Cattermole <alphaglosined gmail.com> writes:
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.
Apr 19 2015
prev sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Sun, 19 Apr 2015 01:19:46 +0000, 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".
=20 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! ;-)=
Apr 18 2015
prev sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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.
Apr 18 2015
parent ketmar <ketmar ketmar.no-ip.org> writes:
On Sun, 19 Apr 2015 01:53:41 +0000, 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".
=20 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. =20 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=20 conflicts. too much delphi in my youth. ;-)=
Apr 18 2015
prev sibling next sibling parent reply "Idan Arye" <GenericNPC gmail.com> writes:
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)?
Apr 19 2015
parent reply "w0rp" <devw0rp gmail.com> writes:
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];
Apr 19 2015
next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
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++?
Apr 19 2015
prev sibling parent Jacob Carlborg <doob me.com> writes:
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
Apr 19 2015
prev sibling next sibling parent reply "Martin Nowak" <code dawg.eu> writes:
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 :)?
Apr 21 2015
parent ketmar <ketmar ketmar.no-ip.org> writes:
On Tue, 21 Apr 2015 22:53:15 +0000, Martin Nowak wrote:

 On Saturday, 18 April 2015 at 15:24:27 UTC, w0rp wrote:
  nogc void main() {
     throw new Foo("Oh no!");
 }
=20 Though until https://issues.dlang.org/show_bug.cgi?id=3D14119 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=20 use statically allocated pool instead, for example. this way functions=20 can throw, yet still be nogc.=
Apr 21 2015
prev sibling parent "Dicebot" <public dicebot.lv> writes:
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.
Apr 23 2015