www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Go, D, and the GC

reply Tourist <gravatar gravatar.com> writes:
Hi Guys,

I know that Go invested many time and resources in an 
implementation of a good GC. And they keep working on it, e.g. 
https://github.com/golang/proposal/blob/master/design/12800-sweep-free-alloc.md

I also see that the implementation is licensed as BSD, as far as 
I see: https://github.com/golang/go/blob/master/LICENSE

Question: is it possible to make a D compiler/runtime that uses 
Go's GC? Wouldn't it largely benefit D? I guess that I'm not the 
first one to think about it. Thoughts?
Oct 01 2015
next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 01-Oct-2015 12:33, Tourist wrote:
 Hi Guys,

 I know that Go invested many time and resources in an implementation of
 a good GC. And they keep working on it, e.g.
 https://github.com/golang/proposal/blob/master/design/12800-sweep-free-alloc.md


 I also see that the implementation is licensed as BSD, as far as I see:
 https://github.com/golang/go/blob/master/LICENSE

 Question: is it possible to make a D compiler/runtime that uses Go's GC?
***memory barriers for pointer writes*** I guess not w/o huge amount of work.
 Wouldn't it largely benefit D? I guess that I'm not the first one to
 think about it. Thoughts?
-- Dmitry Olshansky
Oct 01 2015
prev sibling next sibling parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
On 01/10/15 10:33 PM, Tourist wrote:
 Hi Guys,

 I know that Go invested many time and resources in an implementation of
 a good GC. And they keep working on it, e.g.
 https://github.com/golang/proposal/blob/master/design/12800-sweep-free-alloc.md


 I also see that the implementation is licensed as BSD, as far as I see:
 https://github.com/golang/go/blob/master/LICENSE

 Question: is it possible to make a D compiler/runtime that uses Go's GC?
 Wouldn't it largely benefit D? I guess that I'm not the first one to
 think about it. Thoughts?
We could probably adapt Go's GC to D. But there may not be much point to it. Go and D have very different architectures and styles. Because of this the way data and hence memory is created and consumed is different. Go's GC would have been optimized for Go's patterns and usage of it. We could however read and learn from how it works. But again, we do have some pretty innovate technologies here. They just don't reach druntime. Which is a shame.
Oct 01 2015
parent reply Kagamin <spam here.lot> writes:
On Thursday, 1 October 2015 at 09:40:09 UTC, Rikki Cattermole 
wrote:
 Go's GC would have been optimized for Go's patterns and usage 
 of it.
It's JIT, which usually gets optimized for patterns, the GC pattern is generic: collect the garbage and do it fast.
Oct 01 2015
parent reply rsw0x <anonymous anonymous.com> writes:
On Thursday, 1 October 2015 at 09:48:57 UTC, Kagamin wrote:
 On Thursday, 1 October 2015 at 09:40:09 UTC, Rikki Cattermole 
 wrote:
 Go's GC would have been optimized for Go's patterns and usage 
 of it.
It's JIT,
no?
 which usually gets optimized for patterns, the GC pattern is 
 generic: collect the garbage and do it fast.
No, no it's not. Go's GC has a massive overhead because it's intended to have low latency because that's what Go programs typically require. Go's GC is actually pretty slow by design.
Oct 01 2015
parent reply Kagamin <spam here.lot> writes:
On Friday, 2 October 2015 at 01:21:15 UTC, rsw0x wrote:
 No, no it's not. Go's GC has a massive overhead because it's 
 intended to have low latency because that's what Go programs 
 typically require.
 Go's GC is actually pretty slow by design.
Low latency (also a synonym for fast) is required by interactive applications like client and server software, not by Go itself. Partially interactive data processing programs like compilers prefer optimization for total execution time. GC improvements can show in both scenarios, can depend on usage profile.
Oct 02 2015
parent reply Vladimir Panteleev <thecybershadow.lists gmail.com> writes:
On Friday, 2 October 2015 at 07:32:02 UTC, Kagamin wrote:
 Low latency (also a synonym for fast) is required by 
 interactive applications like client and server software
Isn't a typical collection cycle's duration negligible compared to typical network latency?
Oct 03 2015
parent reply deadalnix <deadalnix gmail.com> writes:
On Saturday, 3 October 2015 at 13:35:19 UTC, Vladimir Panteleev 
wrote:
 On Friday, 2 October 2015 at 07:32:02 UTC, Kagamin wrote:
 Low latency (also a synonym for fast) is required by 
 interactive applications like client and server software
Isn't a typical collection cycle's duration negligible compared to typical network latency?
Not really, especially if you have to block all threads, meaning hundreds of requests.
Oct 03 2015
parent reply Vladimir Panteleev <thecybershadow.lists gmail.com> writes:
On Saturday, 3 October 2015 at 18:21:55 UTC, deadalnix wrote:
 On Saturday, 3 October 2015 at 13:35:19 UTC, Vladimir Panteleev 
 wrote:
 On Friday, 2 October 2015 at 07:32:02 UTC, Kagamin wrote:
 Low latency (also a synonym for fast) is required by 
 interactive applications like client and server software
Isn't a typical collection cycle's duration negligible compared to typical network latency?
Not really, especially if you have to block all threads, meaning hundreds of requests.
I don't understand how that is relevant. E.g. how is making 1% of requests take 100ms longer worse than making 100% of requests take 10ms longer?
Oct 03 2015
parent reply deadalnix <deadalnix gmail.com> writes:
On Saturday, 3 October 2015 at 18:26:32 UTC, Vladimir Panteleev 
wrote:
 On Saturday, 3 October 2015 at 18:21:55 UTC, deadalnix wrote:
 On Saturday, 3 October 2015 at 13:35:19 UTC, Vladimir 
 Panteleev wrote:
 On Friday, 2 October 2015 at 07:32:02 UTC, Kagamin wrote:
 Low latency (also a synonym for fast) is required by 
 interactive applications like client and server software
Isn't a typical collection cycle's duration negligible compared to typical network latency?
Not really, especially if you have to block all threads, meaning hundreds of requests.
I don't understand how that is relevant. E.g. how is making 1% of requests take 100ms longer worse than making 100% of requests take 10ms longer?
Let's say you have capacity on you server to serve 100 requests and a request takes 100ms to process. Then you need to dimension your infra for you servers to absorb 1 request per ms per server. Now you need to stop operation for 100ms to do a GC cycle. In the meantime, requests continue arriving. By the end of the GC cycle, you have 100 more requests to process. Twice as much. The problem is that you are creating a peak demand and need to be able to absorb it. This is a serious problem, in fact, twitter have a very complex system to get machine that are GCing out the load balancer and back at the end of the cycle. This is one way to do it, but it is far from ideal as now re-configuring the load balancer is part of the GC cycle. TL;DR: it is not bad for a user individually, it is bad because it creates peaks of demand on your server you need to absorb.
Oct 03 2015
parent reply welkam <wwwelkam gmail.com> writes:
D gives users tools to avoid heap allocations and if it is 
necessary to allocate heap memory you have scoped memory 
management or ref counting so your GC heap is small or non 
existent. People fear manual memory management because they hear 
stories about C but for most part it can be easy and safe.
Oct 03 2015
parent reply rsw0x <anonymous anonymous.com> writes:
On Saturday, 3 October 2015 at 19:01:33 UTC, welkam wrote:
 D gives users tools to avoid heap allocations and if it is 
 necessary to allocate heap memory you have scoped memory 
 management or ref counting so your GC heap is small or non 
 existent. People fear manual memory management because they 
 hear stories about C but for most part it can be easy and safe.
these tools are not very good and they don't help when the standard library(...or builtin language features...) use the GC and tie your hands
Oct 04 2015
parent reply welkam <wwwelkam gmail.com> writes:
On Sunday, 4 October 2015 at 12:40:00 UTC, rsw0x wrote:
 these tools are not very good and they don't help when the 
 standard library(...or builtin language features...) use the GC 
 and tie your hands
IMO tools for memory management in D are way better than that of other languages. Game developers who use c++ dont use all of c++ features(templates, exceptions), because they care about performance the same can be said about D. Yes some features use GC heap, but you can just not use it. Or you can use so little that GC collection wont even kick in. With Go you have no real option but to use GC.
Oct 04 2015
parent reply Shachar Shemesh <shachar weka.io> writes:
On 04/10/15 19:14, welkam wrote:
 On Sunday, 4 October 2015 at 12:40:00 UTC, rsw0x wrote:
 these tools are not very good and they don't help when the standard
 library(...or builtin language features...) use the GC and tie your hands
IMO tools for memory management in D are way better than that of other languages. Game developers who use c++ dont use all of c++ features(templates, exceptions), because they care about performance the same can be said about D. Yes some features use GC heap, but you can just not use it. Or you can use so little that GC collection wont even kick in. With Go you have no real option but to use GC.
When D structs has a destructor that is guaranteed to run for any instance that finished construction, no matter what is the use case, then we can have that discussion. Until then, no, D's mechanisms for non-heap allocations are vastly inferior to C++'s. Shachar
Oct 04 2015
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 05-Oct-2015 09:52, Shachar Shemesh wrote:
 On 04/10/15 19:14, welkam wrote:
 On Sunday, 4 October 2015 at 12:40:00 UTC, rsw0x wrote:
 these tools are not very good and they don't help when the standard
 library(...or builtin language features...) use the GC and tie your
 hands
IMO tools for memory management in D are way better than that of other languages. Game developers who use c++ dont use all of c++ features(templates, exceptions), because they care about performance the same can be said about D. Yes some features use GC heap, but you can just not use it. Or you can use so little that GC collection wont even kick in. With Go you have no real option but to use GC.
When D structs has a destructor that is guaranteed to run for any instance that finished construction, no matter what is the use case, then we can have that discussion.
Supposed to be the case for structs except for any bugs.
 Until then, no, D's mechanisms for non-heap allocations are vastly
 inferior to C++'s.
Well need some helpers for RC/on stack classes plus kill that horrible extra monitor field. Otherwise I fail to see how. Plus with D's everything is movable by default. I mean I can memcpy D's structs just fine _by spec_ provided that I bitblit T.init over the source. In C++ you can't - not only self-references are permitted but also there is no T.init so there is no bit-pattern that is guaranteed to not explode in dtor.
 Shachar
-- Dmitry Olshansky
Oct 05 2015
next sibling parent reply deadalnix <deadalnix gmail.com> writes:
On Monday, 5 October 2015 at 07:01:35 UTC, Dmitry Olshansky wrote:
 Supposed to be the case for structs except for any bugs.
Not on the heap. There are many cases where the destructor won't run and it is allowed by spec. We should do better.
 Until then, no, D's mechanisms for non-heap allocations are 
 vastly
 inferior to C++'s.
Well need some helpers for RC/on stack classes plus kill that horrible extra monitor field. Otherwise I fail to see how. Plus with D's everything is movable by default. I mean I can memcpy D's structs just fine _by spec_ provided that I bitblit T.init over the source. In C++ you can't - not only self-references are permitted but also there is no T.init so there is no bit-pattern that is guaranteed to not explode in dtor.
Guaranteed construct/destruction is actually a desirable feature IMO. You get all kind of extra case int he dtor to care for when you can't ensure proper construction, and it is not always possible to have a meaningful .init value, leading to many useless runtime checks or an invalid dtor.
Oct 05 2015
next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 05-Oct-2015 10:40, deadalnix wrote:
 In C++ you can't - not only self-references are permitted but also
 there is no T.init so there is no bit-pattern that is guaranteed to
 not explode in dtor.
Guaranteed construct/destruction is actually a desirable feature IMO. You get all kind of extra case int he dtor to care for when you can't ensure proper construction, and it is not always possible to have a meaningful .init value, leading to many useless runtime checks or an invalid dtor.
Yes and no, if your type is movable in C++ you have to have a T.init equivalent to leave something behind after move (oops!). Now if the type is not movable it doesn't really burden much to have an invalid state and trigger an assert in dtor to make sure the type is properly initialized. Then: T a; // would trigger assert on dtor T a = T(...); // shouldn't If all states are valid and you still want to guarantee construction that gets tricky. For example for "seconds" struct if we allow negative seconds as in diff of time. (Though I'd just use long.min for the "wrong" flag in this case). -- Dmitry Olshansky
Oct 05 2015
parent reply Shachar Shemesh <shachar weka.io> writes:
On 05/10/15 10:49, Dmitry Olshansky wrote:

 Yes and no, if your type is movable in C++ you have to have a T.init
 equivalent to leave something behind after move (oops!).
No, under C++ you can choose whether it makes sense for your type to be movable or not. No oops at all. C++ does not make any attempt to protect you from your own incompetence. Within that assumption (which some people accept as reasonable and others don't), C++ does the right thing.
 Now if the type is not movable it doesn't really burden much to have an
 invalid state and trigger an assert in dtor to make sure the type is
 properly initialized. Then:

 T a; // would trigger assert on dtor
 T a = T(...); // shouldn't
But how will you detect whether the type has been properly constructed or not?
 If all states are valid and you still want to guarantee construction
 that gets tricky. For example for "seconds" struct if we allow negative
 seconds as in diff of time. (Though I'd just use long.min for the
 "wrong" flag in this case).
But that is a very strong aspect of the C++ paradigm. Saying "you can engineer a type that is valid at any point it is in scope, enforced by the compiler". In fact, it was such a fundamental part of the C++ design that Strastrup had to change a long standing C constraint (variables are only defined at the start of the scope) in order to support it. That change, like many others, has found its way back into C99, so many people today don't even realize it was ever there. Shachar
Oct 05 2015
parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 05-Oct-2015 12:33, Shachar Shemesh wrote:
 On 05/10/15 10:49, Dmitry Olshansky wrote:

 Yes and no, if your type is movable in C++ you have to have a T.init
 equivalent to leave something behind after move (oops!).
No, under C++ you can choose whether it makes sense for your type to be movable or not.
IF you need a movable type. Most types these days ought to be movable to be fast. So it's OOPS after all. e.g. vector<T> is movable hence it has T.init. *Everything non-trivial* in STL now has T.init, including the unique_ptr and shared_ptr. The T.init is hidden somewhat: auto a = unique_ptr<int>(new int); auto b = move(a); // now a is unique_ptr<int>.init that is null Same goes for locks, threads and whatnot. My point is: if it can move, it has T.init. Copyable types that are not movable are a minority IMO. Non-movable were described in the snipped part of my message.
 No oops at all.

 C++ does not make any attempt to protect you from your own incompetence.
Sadly it goes to great lengths to prove your own incompetence. Eventually it does, but that is OT.
 Within that assumption (which some people accept as reasonable and
 others don't), C++ does the right thing.
If I got you right you seem to imply that types that are copyable but not movable are a good thing. I humbly disagree. -- Dmitry Olshansky
Oct 05 2015
prev sibling next sibling parent reply Shachar Shemesh <shachar weka.io> writes:
On 05/10/15 10:40, deadalnix wrote:

 Guaranteed construct/destruction is actually a desirable feature IMO.
 You get all kind of extra case int he dtor to care for when you can't
 ensure proper construction, and it is not always possible to have a
 meaningful .init value, leading to many useless runtime checks or an
 invalid dtor.
What's more, init is used even if you disable this(). The following compile and does what you'd expect (but not what you want): struct S { int d; disable this(); this( int d ) { this.d = d; } } ... S d = S.init; Shachar
Oct 05 2015
parent reply Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Monday, 5 October 2015 at 09:25:30 UTC, Shachar Shemesh wrote:
 What's more, init is used even if you  disable this(). The 
 following compile and does what you'd expect (but not what you 
 want):
 struct S {
    int d;

     disable this();
    this( int d ) {
       this.d = d;
    }
 }


 ...

    S d = S.init;
I don't understand this. How is that not what you want, considering that you explicitly told it to use the init value?
Oct 05 2015
parent reply Shachar Shemesh <shachar weka.io> writes:
On 05/10/15 13:39, Marc Schütz wrote:
 On Monday, 5 October 2015 at 09:25:30 UTC, Shachar Shemesh wrote:
 What's more, init is used even if you  disable this(). The following
 compile and does what you'd expect (but not what you want):
 struct S {
    int d;

     disable this();
    this( int d ) {
       this.d = d;
    }
 }


 ...

    S d = S.init;
I don't understand this. How is that not what you want, considering that you explicitly told it to use the init value?
One of the basics of C++ is that, if you construct the type correctly, then the user of the type cannot use it in a way that will cause inconsistencies. Such a use will not compile. The above shows that you cannot construct such a type in D. The language simply does not allow you to cancel a certain feature of the type in which you are uninterested. Please bear in mind that the init might not be called directly. Programmer A defines a type that should never be uninitialized (i.e. - needs a constructor). Programmer B places an instance of that type inside a containing struct. Programmer C uses that containing struct's init. Such a problem is not easy to catch, even if programmers A, B and C are the same person. Shachar
Oct 05 2015
next sibling parent reply Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Monday, 5 October 2015 at 10:57:57 UTC, Shachar Shemesh wrote:
 On 05/10/15 13:39, Marc Schütz wrote:
 On Monday, 5 October 2015 at 09:25:30 UTC, Shachar Shemesh 
 wrote:
 What's more, init is used even if you  disable this(). The 
 following
 compile and does what you'd expect (but not what you want):
 struct S {
    int d;

     disable this();
    this( int d ) {
       this.d = d;
    }
 }


 ...

    S d = S.init;
I don't understand this. How is that not what you want, considering that you explicitly told it to use the init value?
One of the basics of C++ is that, if you construct the type correctly, then the user of the type cannot use it in a way that will cause inconsistencies. Such a use will not compile. The above shows that you cannot construct such a type in D. The language simply does not allow you to cancel a certain feature of the type in which you are uninterested.
` disable this();` works fine to prevent the user from doing that accidentally. But in your example, this doesn't happen by accident; you explicitly told the compiler to use the .init value. That's not something you do just because you can, you need to have a reason for it. Presumably a user doing this would know what they're doing. I don't think it's reasonable to expect to be able to prevent that, just as you can't forbid the user to do unsafe casts. And arguably, if your type's .init is invalid, then "you're doing it wrong". Besides, that every type has a .init value is a very fundamental part of the language, not just a feature of a particular type. Sure, you use some flexibility for edge cases, but IMO that's a good tradeoff for the general advantages you gain from it.
 Please bear in mind that the init might not be called directly. 
 Programmer A defines a type that should never be uninitialized 
 (i.e. - needs a constructor). Programmer B places an instance 
 of that type inside a containing struct. Programmer C uses that 
 containing struct's init. Such a problem is not easy to catch, 
 even if programmers A, B and C are the same person.
If you use normal declaration, the compiler correctly rejects that: struct A { disable this(); } struct B { A a; } void main() { B b; } // Error: variable xx.main.b default construction is disabled for type B If you'd use B.init, of course you'd get exactly what you ask for, see above.
Oct 05 2015
parent Kagamin <spam here.lot> writes:
On Monday, 5 October 2015 at 11:41:11 UTC, Marc Schütz wrote:
 ` disable this();` works fine to prevent the user from doing 
 that accidentally. But in your example, this doesn't happen by 
 accident; you explicitly told the compiler to use the .init 
 value. That's not something you do just because you can, you 
 need to have a reason for it. Presumably a user doing this 
 would know what they're doing.
Do it by accident: T safeFront(T[] r) { if(r.length==0)return T.init; return r[0]; }
Oct 05 2015
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 10/05/2015 12:57 PM, Shachar Shemesh wrote:
 On 05/10/15 13:39, Marc Schütz wrote:
 On Monday, 5 October 2015 at 09:25:30 UTC, Shachar Shemesh wrote:
 What's more, init is used even if you  disable this(). The following
 compile and does what you'd expect (but not what you want):
 struct S {
    int d;

     disable this();
    this( int d ) {
       this.d = d;
    }
 }


 ...

    S d = S.init;
I don't understand this. How is that not what you want, considering that you explicitly told it to use the init value?
One of the basics of C++ is that, if you construct the type correctly, then the user of the type cannot use it in a way that will cause inconsistencies. Such a use will not compile. The above shows that you cannot construct such a type in D. The language simply does not allow you to cancel a certain feature of the type in which you are uninterested. Please bear in mind that the init might not be called directly. Programmer A defines a type that should never be uninitialized (i.e. - needs a constructor). Programmer B places an instance of that type inside a containing struct. Programmer C uses that containing struct's init. Such a problem is not easy to catch, even if programmers A, B and C are the same person. Shachar
struct S{ disable this(); disable enum init=0; } void main(){ S s; // error auto d=S.init; // error }
Oct 07 2015
next sibling parent reply Meta <jared771 gmail.com> writes:
On Wednesday, 7 October 2015 at 09:59:05 UTC, Timon Gehr wrote:
 struct S{
      disable this();
      disable enum init=0;
 }

 void main(){
     S s; // error
     auto d=S.init; // error
 }
That's just awful.
Oct 07 2015
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, 7 October 2015 at 14:13:38 UTC, Meta wrote:
 On Wednesday, 7 October 2015 at 09:59:05 UTC, Timon Gehr wrote:
 struct S{
      disable this();
      disable enum init=0;
 }

 void main(){
     S s; // error
     auto d=S.init; // error
 }
That's just awful.
Being able to declare a member named init is just asking for trouble... https://issues.dlang.org/show_bug.cgi?id=14237 https://issues.dlang.org/show_bug.cgi?id=7066 - Jonathan M Davis
Oct 07 2015
next sibling parent reply Meta <jared771 gmail.com> writes:
On Wednesday, 7 October 2015 at 14:50:52 UTC, Jonathan M Davis 
wrote:
 Being able to declare a member named init is just asking for 
 trouble...

 https://issues.dlang.org/show_bug.cgi?id=14237
 https://issues.dlang.org/show_bug.cgi?id=7066

 - Jonathan M Davis
Yeah, no arguments there. This needs to be properly disallowed in the compiler.
Oct 07 2015
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 10/07/2015 06:52 PM, Meta wrote:
 On Wednesday, 7 October 2015 at 14:50:52 UTC, Jonathan M Davis wrote:
 Being able to declare a member named init is just asking for trouble...

 https://issues.dlang.org/show_bug.cgi?id=14237
 https://issues.dlang.org/show_bug.cgi?id=7066

 - Jonathan M Davis
Yeah, no arguments there. This needs to be properly disallowed in the compiler.
The use case I have shown needs a proper migration path though.
Oct 07 2015
prev sibling parent Kapps <opantm2+spam gmail.com> writes:
On Wednesday, 7 October 2015 at 14:50:52 UTC, Jonathan M Davis 
wrote:
 On Wednesday, 7 October 2015 at 14:13:38 UTC, Meta wrote:
 On Wednesday, 7 October 2015 at 09:59:05 UTC, Timon Gehr wrote:
 struct S{
      disable this();
      disable enum init=0;
 }

 void main(){
     S s; // error
     auto d=S.init; // error
 }
That's just awful.
Being able to declare a member named init is just asking for trouble... https://issues.dlang.org/show_bug.cgi?id=14237 https://issues.dlang.org/show_bug.cgi?id=7066 - Jonathan M Davis
https://issues.dlang.org/show_bug.cgi?id=12233 is also related and incredibly bug-prone.
Oct 07 2015
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 10/07/2015 04:13 PM, Meta wrote:
 On Wednesday, 7 October 2015 at 09:59:05 UTC, Timon Gehr wrote:
 struct S{
      disable this();
      disable enum init=0;
 }

 void main(){
     S s; // error
     auto d=S.init; // error
 }
That's just awful.
I was responding to:
 The above shows that you cannot construct such a type in D. The
 language simply does not allow you to cancel a certain feature
 of the type in which you are uninterested.
Obviously there should be a nicer way to do this, but the above claim is simply untrue.
Oct 07 2015
parent Meta <jared771 gmail.com> writes:
On Wednesday, 7 October 2015 at 18:38:34 UTC, Timon Gehr wrote:
 On 10/07/2015 04:13 PM, Meta wrote:
 On Wednesday, 7 October 2015 at 09:59:05 UTC, Timon Gehr wrote:
 struct S{
      disable this();
      disable enum init=0;
 }

 void main(){
     S s; // error
     auto d=S.init; // error
 }
That's just awful.
I was responding to:
Yeah, I was just expressing my disgust that D allows this.
Oct 07 2015
prev sibling parent reply Shachar Shemesh <shachar weka.io> writes:
On 07/10/15 12:58, Timon Gehr wrote:

 Shachar
struct S{ disable this(); disable enum init=0; } void main(){ S s; // error auto d=S.init; // error }
An honest question. Would that also cover all cases where init is being used implicitly by the compiler? I will need to do some research myself, but my gut feeling is "no". There are several cases where the compiler replaces the value with the init value, and I doubt your horrid hack changes that. Either way, I think you'll agree that D needs to be better in defining what is the correct path to take on this, as, currently, nobody seems to know for sure. Shachar
Oct 07 2015
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 10/08/2015 05:20 AM, Shachar Shemesh wrote:
 On 07/10/15 12:58, Timon Gehr wrote:

 Shachar
struct S{ disable this(); disable enum init=0; } void main(){ S s; // error auto d=S.init; // error }
An honest question. Would that also cover all cases where init is being used implicitly by the compiler? ...
Construction does not currently work without init, but there it is no problem. Anyway, the right question is whether there is any way that the invariant of a type can be broken by bypassing the constructor using only safe features. That's actually what disable this() should prevent, apparently modulo explicit usages of init (which does not make that much sense).
 I will need to do some research myself, but my gut feeling is "no".
 There are several cases where the compiler replaces the value with the
 init value, and I doubt your horrid hack changes that.
 ...
I would consider any way that init sneaks in unexpectedly to be a compiler bug related to disable this().
 Either way, I think you'll agree that D needs to be better in defining
 what is the correct path to take on this, as, currently, nobody seems to
 know for sure.
Obviously. Overriding of init should be removed and the use case should be supported in a different way. (This could probably just be, e.g., make disable this() also disable init.) I just showed what we've got, and, for better or worse, it's actually in the language by design.
Oct 08 2015
prev sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 5 October 2015 at 07:40:35 UTC, deadalnix wrote:
 Not on the heap. There are many cases where the destructor 
 won't run and it is allowed by spec. We should do better.
To be fair, if you new a struct in C++ and never delete it, the destructor will never run there either. D's in the same boat in that regard.
Oct 05 2015
parent reply Marco Leise <Marco.Leise gmx.de> writes:
Am Mon, 05 Oct 2015 13:42:50 +0000
schrieb Adam D. Ruppe <destructionator gmail.com>:

 On Monday, 5 October 2015 at 07:40:35 UTC, deadalnix wrote:
 Not on the heap. There are many cases where the destructor 
 won't run and it is allowed by spec. We should do better.
To be fair, if you new a struct in C++ and never delete it, the destructor will never run there either. D's in the same boat in that regard.
But the D boat reads "Garbage Collector". And besides, D now runs dtors on new'd structs. The "many cases" may be different ones than you imagine. -- Marco
Oct 08 2015
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Thursday, 8 October 2015 at 15:58:37 UTC, Marco Leise wrote:
 Am Mon, 05 Oct 2015 13:42:50 +0000
 schrieb Adam D. Ruppe <destructionator gmail.com>:

 On Monday, 5 October 2015 at 07:40:35 UTC, deadalnix wrote:
 Not on the heap. There are many cases where the destructor 
 won't run and it is allowed by spec. We should do better.
To be fair, if you new a struct in C++ and never delete it, the destructor will never run there either. D's in the same boat in that regard.
But the D boat reads "Garbage Collector". And besides, D now runs dtors on new'd structs. The "many cases" may be different ones than you imagine.
It's still the case though that if the GC does not collect a struct on the GC heap, its destructor is not going to be run. And there's no guarantee that _anything_ on the GC heap will ever be collected. That depends on stuff like the memory usage of the program. We're better off than we were, because when a struct on the GC heap is collected, it's destructor will now be run, whereas it wouldn't have been before, but ultimately, it's still the same boat as C++ with regards to structs that never get collected. It's just that in C++, you don't usually let memory leak like that, whereas a GC doesn't normally collect everything when the program shuts down. So, you're unlikely to run into a case in C++ where a struct never gets destroyed, whereas it's pretty easy in D. - Jonathan M Davis
Oct 08 2015
prev sibling parent reply Shachar Shemesh <shachar weka.io> writes:
On 08/10/15 18:58, Marco Leise wrote:
 Am Mon, 05 Oct 2015 13:42:50 +0000
 schrieb Adam D. Ruppe <destructionator gmail.com>:

 On Monday, 5 October 2015 at 07:40:35 UTC, deadalnix wrote:
 Not on the heap. There are many cases where the destructor
 won't run and it is allowed by spec. We should do better.
To be fair, if you new a struct in C++ and never delete it, the destructor will never run there either. D's in the same boat in that regard.
But the D boat reads "Garbage Collector". And besides, D now runs dtors on new'd structs. The "many cases" may be different ones than you imagine.
There is an inherent contradiction between GC and destruction. The GC's unpredictable nature runs counter to the reason you usually want a struct to have a destructor in the first place. With that said, D has improved on that front. By this discussion started out with using containers in order to avoid using the GC. As such, those cases are less relevant to this discussion, I think. You'll also notice that the C++ heap does not suffer from unpredictability. You either delete at a specified time (typically, from some RAII's destructor), or leak it, in which case, well, you leaked it. Shachar
Oct 09 2015
parent reply deadalnix <deadalnix gmail.com> writes:
On Friday, 9 October 2015 at 07:39:06 UTC, Shachar Shemesh wrote:
 On 08/10/15 18:58, Marco Leise wrote:
 Am Mon, 05 Oct 2015 13:42:50 +0000
 schrieb Adam D. Ruppe <destructionator gmail.com>:

 On Monday, 5 October 2015 at 07:40:35 UTC, deadalnix wrote:
 Not on the heap. There are many cases where the destructor
 won't run and it is allowed by spec. We should do better.
To be fair, if you new a struct in C++ and never delete it, the destructor will never run there either. D's in the same boat in that regard.
But the D boat reads "Garbage Collector". And besides, D now runs dtors on new'd structs. The "many cases" may be different ones than you imagine.
There is an inherent contradiction between GC and destruction. The GC's unpredictable nature runs counter to the reason you usually want a struct to have a destructor in the first place. With that said, D has improved on that front. By this discussion started out with using containers in order to avoid using the GC. As such, those cases are less relevant to this discussion, I think. You'll also notice that the C++ heap does not suffer from unpredictability. You either delete at a specified time (typically, from some RAII's destructor), or leak it, in which case, well, you leaked it. Shachar
Well it depends. destruction and GC are about releasing resources. You want eager resource release for scarce resources, like file handler. For resources that aren't as scarce, strategy like GC make sense. But GC only works for memory. One also may want to GC other resources, granted they aren't too scarce. dtor make sense for this. It is also very useful as a safety net. When the object is released, if it still hold handle to scarce resource, it make sense to log and release it, or something similar. That is surely better than running out of the resource and crashing.
Oct 09 2015
parent Kagamin <spam here.lot> writes:
On Friday, 9 October 2015 at 07:54:43 UTC, deadalnix wrote:
 It is also very useful as a safety net. When the object is 
 released, if it still hold handle to scarce resource, it make 
 sense to log and release it, or something similar. That is 
 surely better than running out of the resource and crashing.
Though it's a feature nice to have, not a resource management mechanism. In .net when an object is released it can suppress its finalizer, so it won't be considered for finalization during collection and will be collected as plain garbage. AFAIK in D GC finalization is accounted as a block flag, so to suppress finalization one can reset this flag, and the block will be collected without finalization.
Oct 09 2015
prev sibling parent reply Shachar Shemesh <shachar weka.io> writes:
On 05/10/15 10:01, Dmitry Olshansky wrote:

 When D structs has a destructor that is guaranteed to run for any
 instance that finished construction, no matter what is the use case,
 then we can have that discussion.
Supposed to be the case for structs except for any bugs.
Check this one out (no instances on heap): import std.stdio; struct destructible { int id; disable this(); this( int id ) { writeln("Id ", id, " constructed"); this.id = id; } ~this() { writeln("Id ", id, " destructed"); } } void main() { struct container { destructible d; disable this(); this( int id ) { this.d = destructible(id); throw new Exception("some random exception"); } } try { container(2); } catch( Exception ex ) { writeln("Caught ", ex.msg); } } As of dmd 2.068.2, the output is: Id 2 constructed Caught Some random exception Of course, if I do not disable this(), things are even worse.
Oct 05 2015
parent reply Marco Leise <Marco.Leise gmx.de> writes:
Am Mon, 5 Oct 2015 12:22:59 +0300
schrieb Shachar Shemesh <shachar weka.io>:

 On 05/10/15 10:01, Dmitry Olshansky wrote:
 
 When D structs has a destructor that is guaranteed to run for any
 instance that finished construction, no matter what is the use case,
 then we can have that discussion.
Supposed to be the case for structs except for any bugs.
Check this one out (no instances on heap): import std.stdio; struct destructible { int id; disable this(); this( int id ) { writeln("Id ", id, " constructed"); this.id = id; } ~this() { writeln("Id ", id, " destructed"); } } void main() { struct container { destructible d; disable this(); this( int id ) { this.d = destructible(id); throw new Exception("some random exception"); } } try { container(2); } catch( Exception ex ) { writeln("Caught ", ex.msg); } } As of dmd 2.068.2, the output is: Id 2 constructed Caught Some random exception Of course, if I do not disable this(), things are even worse.
Damn this is sneaky! Now the statements "When D structs has a destructor that is guaranteed to run for any instance that finished construction." "When construction fails, the dtor is not run on that half-constructed object. Instead it is the ctors responsibility to roll back its actions." collide with a struct that finished construction embedded in a struct that failed construction. This is a deadlock. -- Marco
Oct 08 2015
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 10/08/2015 06:09 PM, Marco Leise wrote:
 Am Mon, 5 Oct 2015 12:22:59 +0300
 schrieb Shachar Shemesh <shachar weka.io>:

 On 05/10/15 10:01, Dmitry Olshansky wrote:

 When D structs has a destructor that is guaranteed to run for any
 instance that finished construction, no matter what is the use case,
 then we can have that discussion.
Supposed to be the case for structs except for any bugs.
Check this one out (no instances on heap): import std.stdio; struct destructible { int id; disable this(); this( int id ) { writeln("Id ", id, " constructed"); this.id = id; } ~this() { writeln("Id ", id, " destructed"); } } void main() { struct container { destructible d; disable this(); this( int id ) { this.d = destructible(id); throw new Exception("some random exception"); } } try { container(2); } catch( Exception ex ) { writeln("Caught ", ex.msg); } } As of dmd 2.068.2, the output is: Id 2 constructed Caught Some random exception Of course, if I do not disable this(), things are even worse.
Damn this is sneaky! Now the statements "When D structs has a destructor that is guaranteed to run for any instance that finished construction." "When construction fails, the dtor is not run on that half-constructed object. Instead it is the ctors responsibility to roll back its actions." collide with a struct that finished construction embedded in a struct that failed construction. This is a deadlock.
Why? As I interpret those two statements, the fields that have finished construction should just be destroyed even if the enclosing object has not finished construction (and is hence not destroyed).
Oct 08 2015
prev sibling next sibling parent Jack Stouffer <jack jackstouffer.com> writes:
On Thursday, 1 October 2015 at 09:33:26 UTC, Tourist wrote:
 Hi Guys,

 I know that Go invested many time and resources in an 
 implementation of a good GC. And they keep working on it, e.g. 
 https://github.com/golang/proposal/blob/master/design/12800-sweep-free-alloc.md

 I also see that the implementation is licensed as BSD, as far 
 as I see: https://github.com/golang/go/blob/master/LICENSE

 Question: is it possible to make a D compiler/runtime that uses 
 Go's GC? Wouldn't it largely benefit D? I guess that I'm not 
 the first one to think about it. Thoughts?
This topic was discussed here: http://forum.dlang.org/thread/iohdxjqvcetesloxbwfh forum.dlang.org
Oct 01 2015
prev sibling parent reply Iain Buclaw via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 1 Oct 2015 11:35 am, "Tourist via Digitalmars-d" <
digitalmars-d puremagic.com> wrote:
 Hi Guys,

 I know that Go invested many time and resources in an implementation of a
good GC. And they keep working on it, e.g. https://github.com/golang/proposal/blob/master/design/12800-sweep-free-alloc.md
 I also see that the implementation is licensed as BSD, as far as I see:
https://github.com/golang/go/blob/master/LICENSE
 Question: is it possible to make a D compiler/runtime that uses Go's GC?
Wouldn't it largely benefit D? I guess that I'm not the first one to think about it. Thoughts? Why do you think Go's GC might be better than D's? Is it because we lack the PR when changes/innovations are done to the GC in druntime? Do you *know* about anything new that has changed or improved in D's GC over the last two years? I'd be interested to hear about this.
Oct 01 2015
parent reply Tourist <gravatar gravatar.com> writes:
On Friday, 2 October 2015 at 06:53:56 UTC, Iain Buclaw wrote:
 On 1 Oct 2015 11:35 am, "Tourist via Digitalmars-d" < 
 digitalmars-d puremagic.com> wrote:
 [...]
good GC. And they keep working on it, e.g. https://github.com/golang/proposal/blob/master/design/12800-sweep-free-alloc.md
 [...]
https://github.com/golang/go/blob/master/LICENSE
 [...]
Wouldn't it largely benefit D? I guess that I'm not the first one to think about it. Thoughts? Why do you think Go's GC might be better than D's? Is it because we lack the PR when changes/innovations are done to the GC in druntime? Do you *know* about anything new that has changed or improved in D's GC over the last two years? I'd be interested to hear about this.
I know that it has the reputation of being of the simplest kind. Haven't looked at the code actually (and I wouldn't understand much even if I did).
Oct 02 2015
next sibling parent reply Iain Buclaw via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 2 Oct 2015 1:32 pm, "Tourist via Digitalmars-d" <
digitalmars-d puremagic.com> wrote:
 On Friday, 2 October 2015 at 06:53:56 UTC, Iain Buclaw wrote:
 On 1 Oct 2015 11:35 am, "Tourist via Digitalmars-d" <
digitalmars-d puremagic.com> wrote:
 [...]
good GC. And they keep working on it, e.g.
https://github.com/golang/proposal/blob/master/design/12800-sweep-free-alloc.md
 [...]
https://github.com/golang/go/blob/master/LICENSE
 [...]
Wouldn't it largely benefit D? I guess that I'm not the first one to
think about it. Thoughts?
 Why do you think Go's GC might be better than D's?  Is it because we
lack the PR when changes/innovations are done to the GC in druntime? Do you *know* about anything new that has changed or improved in D's GC over the last two years?
 I'd be interested to hear about this.
I know that it has the reputation of being of the simplest kind. Haven't
looked at the code actually (and I wouldn't understand much even if I did). So I doubt you've looked at Go's GC code either. In which case it is a matter of PR which led to your suggestion.
Oct 03 2015
parent Tourist <gravatar gravatar.com> writes:
On Saturday, 3 October 2015 at 07:49:35 UTC, Iain Buclaw wrote:
 On 2 Oct 2015 1:32 pm, "Tourist via Digitalmars-d" < 
 digitalmars-d puremagic.com> wrote:
 On Friday, 2 October 2015 at 06:53:56 UTC, Iain Buclaw wrote:
 On 1 Oct 2015 11:35 am, "Tourist via Digitalmars-d" <
digitalmars-d puremagic.com> wrote:
 [...]
good GC. And they keep working on it, e.g.
https://github.com/golang/proposal/blob/master/design/12800-sweep-free-alloc.md
 [...]
https://github.com/golang/go/blob/master/LICENSE
 [...]
Wouldn't it largely benefit D? I guess that I'm not the first one to
think about it. Thoughts?
 Why do you think Go's GC might be better than D's?  Is it 
 because we
lack the PR when changes/innovations are done to the GC in druntime? Do you *know* about anything new that has changed or improved in D's GC over the last two years?
 I'd be interested to hear about this.
I know that it has the reputation of being of the simplest kind. Haven't
looked at the code actually (and I wouldn't understand much even if I did). So I doubt you've looked at Go's GC code either. In which case it is a matter of PR which led to your suggestion.
That's basically true, but isn't it a good approximation of the real state of affairs? My comment about the D GC being of the simple kind was something I've read here on the forums, not on e.g. Reddit or the Go forums, so it's probably approximately true (why would you falsely bash yourself?). And Google, being a huge company, can invest a lot in Go, which includes the GC, and the fact that there are articles about its improvements here and there suggests that they do invest a lot.
Oct 04 2015
prev sibling parent reply Martin Nowak <code dawg.eu> writes:
On Friday, 2 October 2015 at 11:27:12 UTC, Tourist wrote:
 I know that it has the reputation of being of the simplest 
 kind. Haven't looked at the code actually (and I wouldn't 
 understand much even if I did).
Go has a very simple GC itself. It's concurrent, so it trades low latency against performance (write-barriers) and throughput. We wouldn't want to force everybody to use write-barriers, but you can avoid creating garbage in D much easier (e.g. map) and we're improving support for deterministic memory management. So while we keep on improving D's GC as well, GC performance is less of a problem in D b/c you have a smaller GC heap.
Oct 04 2015
parent reply rsw0x <anonymous anonymous.com> writes:
On Sunday, 4 October 2015 at 17:22:52 UTC, Martin Nowak wrote:
 On Friday, 2 October 2015 at 11:27:12 UTC, Tourist wrote:
 I know that it has the reputation of being of the simplest 
 kind. Haven't looked at the code actually (and I wouldn't 
 understand much even if I did).
Go has a very simple GC itself. It's concurrent, so it trades low latency against performance (write-barriers) and throughput. We wouldn't want to force everybody to use write-barriers, but you can avoid creating garbage in D much easier (e.g. map) and we're improving support for deterministic memory management. So while we keep on improving D's GC as well, GC performance is less of a problem in D b/c you have a smaller GC heap.
I still say it's worth investigating a thread-local GC by taking advantage of the fact that shared has never really been properly fleshed out. This would heavily play to D's TLS by default, and preferring message passing over shared data. Bye.
Oct 04 2015
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, 4 October 2015 at 17:30:39 UTC, rsw0x wrote:
 I still say it's worth investigating a thread-local GC by 
 taking advantage of the fact that shared has never really been 
 properly fleshed out. This would heavily play to D's TLS by 
 default, and preferring message passing over shared data.
That would be ideal but gets really nasty for a number of reasons - primarily having to do with casting. It's perfectly possible to cast to and from shared and much easier to create something as thread-local and then cast it to shared than to create it as shared, so you very quickly run into problems with objects being created on heap but really needing to be used on another. Another major issue is message passing, because in order to avoid copying, you basically need a way to move an object from one thread-local heap to another. Right now the way you'd do it is to cast to immutable to pass the object and cast it back to mutable on the other side (which is _far_ from ideal). Using shared would be better, but the last time I checked, Variant has issues with it so that that didn't work with std.concurrency. Regardless, the fact that you're casting to pass across threads again runs into issues with objects being created on a particular heap but then needing to be moved to another. _Maybe_ that could be resolved by making casting to and from shared do a lot more work underneath the hood, but that get's _really_ complicated when you start having objects that refer to other objects and the like. So, having a thread-local GC _sounds_ like a great idea, but it's not at all clear that we can actually pull it off given how much you're allowed to do in D. There can be some serious downsides to not placing major restrictions on the user like languages like Java or Go tend to do. - Jonathan M Davis
Oct 04 2015
next sibling parent reply rsw0x <anonymous anonymous.com> writes:
On Sunday, 4 October 2015 at 21:01:45 UTC, Jonathan M Davis wrote:
 On Sunday, 4 October 2015 at 17:30:39 UTC, rsw0x wrote:
 I still say it's worth investigating a thread-local GC by 
 taking advantage of the fact that shared has never really been 
 properly fleshed out. This would heavily play to D's TLS by 
 default, and preferring message passing over shared data.
That would be ideal but gets really nasty for a number of reasons - primarily having to do with casting. It's perfectly possible to cast to and from shared and much easier to create something as thread-local and then cast it to shared than to create it as shared, so you very quickly run into problems with objects being created on heap but really needing to be used on another. Another major issue is message passing, because in order to avoid copying, you basically need a way to move an object from one thread-local heap to another. Right now the way you'd do it is to cast to immutable to pass the object and cast it back to mutable on the other side (which is _far_ from ideal). Using shared would be better, but the last time I checked, Variant has issues with it so that that didn't work with std.concurrency. Regardless, the fact that you're casting to pass across threads again runs into issues with objects being created on a particular heap but then needing to be moved to another. _Maybe_ that could be resolved by making casting to and from shared do a lot more work underneath the hood, but that get's _really_ complicated when you start having objects that refer to other objects and the like. So, having a thread-local GC _sounds_ like a great idea, but it's not at all clear that we can actually pull it off given how much you're allowed to do in D. There can be some serious downsides to not placing major restrictions on the user like languages like Java or Go tend to do. - Jonathan M Davis
Most of these issues are addressed by fleshing out shared, it was already put as a 'priority' last year by Andrei but nothing was ever done. If you design a language around having a GC, but do not provide GC friendly mechanisms, the GC will never be good for the language. Java would never have a GC better than a simple mark and sweep GC if it didn't provide help to the GC. Designing shared around the GC just happens to be a way to do it without affecting the runtime performance of D at all unlike e.g, pointer barriers. If D has no intentions of aiding the GC, then the GC should just be dropped because it's basically just slapping Boehm on C++ right now. bye.
Oct 04 2015
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, 4 October 2015 at 21:41:00 UTC, rsw0x wrote:
 If D has no intentions of aiding the GC, then the GC should 
 just be dropped because it's basically just slapping Boehm on 
 C++ right now.
I don't understand this attitude at all (and you're not the only one to voice it lately). D has a ton to offer and so little of it has anything to do with the GC. The delegate/lambda/closure situation is generally saner thanks to the GC (at least as far as safety goes), and arrays have some fantastic features thanks to the GC, but D has _way_ more to offer than that, and most of it has nothing to do with the GC. D's templates alone blow C++ totally out of the water. C++ is a great language, and I love it. But at this point, I only use it when I have to. D is just _so_ much more pleasant to program in that I have no interest in programming in C++ anymore. It's been years since I've done any kind of pet project in C++. - Jonathan M Davis
Oct 04 2015
next sibling parent bitwise <bitwise.pvt gmail.com> writes:
On Sunday, 4 October 2015 at 23:28:48 UTC, Jonathan M Davis wrote:
 D's templates alone blow C++ totally out of the water. - 
 Jonathan M Davis
I have to agree here. This is one feature of D that I can't complain about...at all. I honestly can't think of a single issue I have had with D's templates. Everything just works. Bit
Oct 04 2015
prev sibling parent reply Marco Leise <Marco.Leise gmx.de> writes:
Am Sun, 04 Oct 2015 23:28:47 +0000
schrieb Jonathan M Davis <jmdavisProg gmx.com>:

 On Sunday, 4 October 2015 at 21:41:00 UTC, rsw0x wrote:
 If D has no intentions of aiding the GC, then the GC should 
 just be dropped because it's basically just slapping Boehm on 
 C++ right now.
I don't understand this attitude at all (and you're not the only one to voice it lately). D has a ton to offer and so little of it has anything to do with the GC. The delegate/lambda/closure situation is generally saner thanks to the GC (at least as far as safety goes), and arrays have some fantastic features thanks to the GC, but D has _way_ more to offer than that, and most of it has nothing to do with the GC. D's templates alone blow C++ totally out of the water. C++ is a great language, and I love it. But at this point, I only use it when I have to. D is just _so_ much more pleasant to program in that I have no interest in programming in C++ anymore. It's been years since I've done any kind of pet project in C++. - Jonathan M Davis
It was probably bad wording. I understood it as D's GC works on a similar basis as Boehm now - conservative, stop the world mark & sweep. The reason in both being the nature of the host language. In fact the German Wikipedia says that Boehm GC was ported with minimal changes to druntime. -- Marco
Oct 08 2015
parent rsw0x <anonymous anonymous.com> writes:
On Thursday, 8 October 2015 at 16:25:00 UTC, Marco Leise wrote:
 Am Sun, 04 Oct 2015 23:28:47 +0000
 schrieb Jonathan M Davis <jmdavisProg gmx.com>:

 [...]
It was probably bad wording. I understood it as D's GC works on a similar basis as Boehm now - conservative, stop the world mark & sweep. The reason in both being the nature of the host language. In fact the German Wikipedia says that Boehm GC was ported with minimal changes to druntime.
Yes, this is what I was implying. Sorry if it was poorly worded. D does not provide the GC with any support, it is like dropping boehm in C++.
Oct 08 2015
prev sibling parent Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Sunday, 4 October 2015 at 21:01:45 UTC, Jonathan M Davis wrote:
 That would be ideal but gets really nasty for a number of 
 reasons - primarily having to do with casting. It's perfectly 
 possible to cast to and from shared and much easier to create 
 something as thread-local and then cast it to shared than to 
 create it as shared, so you very quickly run into problems with 
 objects being created on heap but really needing to be used on 
 another. Another major issue is message passing, because in 
 order to avoid copying, you basically need a way to move an 
 object from one thread-local heap to another. Right now the way 
 you'd do it is to cast to immutable to pass the object and cast 
 it back to mutable on the other side (which is _far_ from 
 ideal). Using shared would be better, but the last time I 
 checked, Variant has issues with it so that that didn't work 
 with std.concurrency. Regardless, the fact that you're casting 
 to pass across threads again runs into issues with objects 
 being created on a particular heap but then needing to be moved 
 to another. _Maybe_ that could be resolved by making casting to 
 and from shared do a lot more work underneath the hood, but 
 that get's _really_ complicated when you start having objects 
 that refer to other objects and the like.
It should at least be considered. I wouldn't want write-barriers, but OTOH cast-barriers might be acceptable.
Oct 05 2015