digitalmars.D.learn - GC for noobs
- Szymon Gatner (21/21) Feb 27 2014 Hi,
- Tobias Pankrath (7/12) Feb 27 2014 Parent in the sense of an inheritance hierarchy or in the sense
- Tobias Pankrath (13/20) Feb 27 2014 Spec says:
- Szymon Gatner (9/29) Feb 27 2014 Parent-child in the sense of object graph. I did read the spec
- Tobias Pankrath (3/10) Feb 27 2014 I think that will depend on your use case. Why do you need to
- Szymon Gatner (6/18) Feb 27 2014 I don't need to refer to children, I just want them to do their
- bearophile (5/6) Feb 27 2014 Why? Perhaps if you explain what's behind your needs better,
- Szymon Gatner (24/30) Feb 27 2014 In my specific example I am creating OpenGL Renderer. Renderer
- Namespace (9/42) Feb 27 2014 I had the same problem in Dgame. Therefore I use shared pointers
- Szymon Gatner (8/56) Feb 27 2014 Module d-tor() looks like a pretty good solution, thanks.
- Namespace (5/64) Feb 27 2014 I use this solution especially because I have to finalize the
- Szymon Gatner (4/7) Feb 27 2014 I fully understand that ;)
- Mike Parker (3/7) Feb 27 2014 I've never seen a garbage collected language where the GC guarantees
- Mike Parker (43/52) Feb 27 2014 Two simple rules I follow.
- Remo (15/80) Feb 27 2014 Then the question is why not use structs all the time?
- Dicebot (4/5) Feb 27 2014 Key class feature is run-time polymorphism (via
- Namespace (2/7) Feb 27 2014 Maybe we really should implement ARC classes... :)
- Dicebot (3/11) Feb 27 2014 I don't see how it is relevant. I would not have used ARC classes
- Namespace (2/14) Feb 27 2014 Why not? Overhead? No RAII support?
- Dicebot (5/6) Feb 27 2014 Simply no reason to use classes, structs have all features I need
- Szymon Gatner (10/16) Feb 27 2014 They actually don't have all the necessary features in D afaiu.
- Dicebot (4/13) Feb 27 2014 You can disable postblit to make entity non-copyable:
- Dicebot (5/5) Feb 27 2014 There is also one complex and feature-reach implementation of
- Szymon Gatner (4/9) Feb 27 2014 Tbh it only looks worse and worse to me :(
- Namespace (3/13) Feb 27 2014 Do you know Rust? http://www.rust-lang.org/
- Szymon Gatner (2/17) Feb 27 2014 I do. Do you want me to go away? ;)
- bearophile (6/7) Feb 27 2014 Perhaps for your use case it's better for you to stick with
- Szymon Gatner (11/16) Feb 27 2014 For now I don'r really see alternative. Isn't resource a
- Remo (7/21) Feb 27 2014 Resource management is important part, but part but not every
- Szymon Gatner (2/3) Feb 27 2014 I mean half-implemented buggy version of C++11 in VC2012 ;)
- Remo (3/7) Feb 27 2014 Or in VC2013, but if you can use Intel compiler then it is better.
- Szymon Gatner (4/13) Feb 27 2014 VC2013 at least has variadics... I will not spend another 400
- John Colvin (5/15) Feb 27 2014 Or, alternatively:
- Szymon Gatner (5/22) Feb 27 2014 I dig flexibility, I really do, and I appreciate D's features
- Dicebot (5/9) Feb 28 2014 Resource management (including memory management) is on of most
- Szymon Gatner (16/25) Feb 28 2014 I didn't mean "basic" in the sense of "easy" but in the sense of
- Dicebot (18/29) Feb 28 2014 Yes, it needs to be dealt with all the time but in a different
- Mike Parker (5/9) Feb 28 2014 I have a strong C background as well and have never had any complaints
- Szymon Gatner (6/20) Feb 28 2014 It really is, RAII is the most important idiom in C++, in short
- Dicebot (4/9) Feb 28 2014 Repeating this again and again - you can use RAII. Just not with
- Szymon Gatner (3/14) Feb 28 2014 I know I can, my point is that it is more difficult and I don't
- Mike Parker (2/4) Feb 28 2014 I'm a C folk and I'm really happy :)
- Szymon Gatner (3/9) Feb 28 2014 C'mon, GC has to be an itch for you mallocers :)
- Dicebot (11/14) Feb 28 2014 It sometimes is. In that case we don't use GC.
- Szymon Gatner (10/22) Feb 28 2014 Not really different tho. Actual function call swqence might be
- Xavier Bigand (13/33) Feb 28 2014 I had a lot of difficulties too with the release order of resources. Of
- Regan Heath (12/33) Feb 28 2014 Amen. (Not used religiously)
- Namespace (2/40) Feb 28 2014 Yeah scope -> scoped is IMO such a wrong choice. :)
- Szymon Gatner (6/21) Feb 27 2014 How can I then use it as a function return value? Or store in a
- Dicebot (35/42) Feb 27 2014 Yep, moving ownership is the main issue (as opposed to just
- Adam D. Ruppe (57/60) Feb 27 2014 struct MovingStruct {
- Szymon Gatner (5/65) Feb 27 2014 Wow, that is pretty great stuff. Bit verbose, but gets the job
- Dicebot (3/10) Feb 27 2014 Isn't it exactly what Phobos RefCounted does?
- Adam D. Ruppe (14/15) Feb 27 2014 Yes, though knowing how the implementation works is good for
- Szymon Gatner (9/14) Feb 27 2014 That is very similar to my thoughts atm. Explicit call to init()
- Dicebot (11/18) Feb 27 2014 It is much better than C because of `scope(exit) terminate()`
Hi, I am evaluating D for future projects and coming from C++ I find it really hard to understand semantics of destruction of GC-managed code. After many application-shutdown crashes caused by invalid order of class destructor calls I really think I need to change the way I am thinking about them (and resource management in general I suppose). My crashes (still have them and can't track all as debugging D sucks) are caused by the fact that d-tor of parent object can be called before child d-tors. Adding destroy() calls in parent d-tors helped with some of crashes but I really hate this solution as I was virtually NEVER using 'delete' in C++. I feel like I should be doing things in D very differently than I am doing them in C++. I now think I should be using structs everywhere because I understand them but I do need reference semantics (ideally with unique ownership). Please point me to a literature for C++ programmer that has very little experience with GC/resource management, because at this point I really feel like GC should be easing things and working against me.
Feb 27 2014
On Thursday, 27 February 2014 at 09:49:08 UTC, Szymon Gatner wrote:My crashes (still have them and can't track all as debugging D sucks) are caused by the fact that d-tor of parent object can be called before child d-tors. Adding destroy() calls in parent d-tors helped with some of crashes but I really hate this solution as I was virtually NEVER using 'delete' in C++.Parent in the sense of an inheritance hierarchy or in the sense of a successor relation in a graph of objects? In the latter case the order of destruction is undefined (IMO), i.e. if you have class A { B someB; } where B is a class as well, than B might be already destroyed if A's destructor is run.
Feb 27 2014
On Thursday, 27 February 2014 at 09:55:14 UTC, Tobias Pankrath wrote:On Thursday, 27 February 2014 at 09:49:08 UTC, Szymon Gatner wrote:Spec says: -- The garbage collector is not guaranteed to run the destructor for all unreferenced objects. Furthermore, the order in which the garbage collector calls destructors for unreference objects is not specified. This means that when the garbage collector calls a destructor for an object of a class that has members that are references to garbage collected objects, those references may no longer be valid. >> This means that destructors cannot reference sub objects. << --My crashes (still have them and can't track all as debugging D sucks) are caused by the fact that d-tor of parent object can be called before child d-tors. Adding destroy() calls in parent d-tors helped with some of crashes but I really hate this solution as I was virtually NEVER using 'delete' in C++.
Feb 27 2014
On Thursday, 27 February 2014 at 09:57:51 UTC, Tobias Pankrath wrote:On Thursday, 27 February 2014 at 09:55:14 UTC, Tobias Pankrath wrote:Parent-child in the sense of object graph. I did read the spec when I started to notice crashes. I must say that it really terrified me to my very bones. I always though that higher-level memory management environments would give more and not less guarantees. Anyway, I really need to learn how to design the code for CG and undefined d-tor calls. Any pointers would be welcome.On Thursday, 27 February 2014 at 09:49:08 UTC, Szymon Gatner wrote:Spec says: -- The garbage collector is not guaranteed to run the destructor for all unreferenced objects. Furthermore, the order in which the garbage collector calls destructors for unreference objects is not specified. This means that when the garbage collector calls a destructor for an object of a class that has members that are references to garbage collected objects, those references may no longer be valid. >> This means that destructors cannot reference sub objects. << --My crashes (still have them and can't track all as debugging D sucks) are caused by the fact that d-tor of parent object can be called before child d-tors. Adding destroy() calls in parent d-tors helped with some of crashes but I really hate this solution as I was virtually NEVER using 'delete' in C++.
Feb 27 2014
Szymon Gatner wrote:Parent-child in the sense of object graph. I did read the spec when I started to notice crashes. I must say that it really terrified me to my very bones. I always though that higher-level memory management environments would give more and not less guarantees. Anyway, I really need to learn how to design the code for CG and undefined d-tor calls. Any pointers would be welcome.I think that will depend on your use case. Why do you need to refer to child objects in your destructor?
Feb 27 2014
On Thursday, 27 February 2014 at 10:40:15 UTC, Tobias Pankrath wrote:Szymon Gatner wrote:I don't need to refer to children, I just want them to do their cleanup first as they should. This is basic resource-management stuff, surely there has to be generic advice out there?Parent-child in the sense of object graph. I did read the spec when I started to notice crashes. I must say that it really terrified me to my very bones. I always though that higher-level memory management environments would give more and not less guarantees. Anyway, I really need to learn how to design the code for CG and undefined d-tor calls. Any pointers would be welcome.I think that will depend on your use case. Why do you need to refer to child objects in your destructor?
Feb 27 2014
Szymon Gatner:I just want them to do their cleanup first as they should.Why? Perhaps if you explain what's behind your needs better, people can help better. Bye, bearophile
Feb 27 2014
On Thursday, 27 February 2014 at 11:13:17 UTC, bearophile wrote:Szymon Gatner:In my specific example I am creating OpenGL Renderer. Renderer class instance holds GLContext instance. After context creation GL objects are created like textures and vertex buffers. Those are Texture and VertexBuffer class instances too. It is critical that those child resources are freed before GL context is destroyed. Thing is, even tho Renderer keeps list of Textures , VertexBuffers and Context object, order of their destruction is completely undefined making Context d-tor called first and then child resources d-tors which ends in catastrophe. In C++ (which has a LOT of problems) this is a no-brainer. Order of d-tors is fully defined. Sub-objects are destroyed before parent d-tor is called so only thing to worry about is the order of definition of members. This is just an example but I would think that it is something rather important to have... What about child objects un-registering themselves in d-tors from a list that parent object holds and parent is destroyed first? What about asynchronous completion handler object that should notify some other object that it finished/not finished a job but a notifee is already destroyed because application is being shut-down? I honestly can't imagine how to reason about object graph lifetimes in GC world and I am sure I am missing something very basic. Probably a very different mindset.I just want them to do their cleanup first as they should.Why? Perhaps if you explain what's behind your needs better, people can help better. Bye, bearophile
Feb 27 2014
On Thursday, 27 February 2014 at 12:25:49 UTC, Szymon Gatner wrote:On Thursday, 27 February 2014 at 11:13:17 UTC, bearophile wrote:I had the same problem in Dgame. Therefore I use shared pointers (https://github.com/Dgame/Dgame/blob/master/Graphics/Surface.d#L90) or if I have to use classes, I use this: https://github.com/Dgame/Dgame/blob/master/Window/Window.d#L44 https://github.com/Dgame/Dgame/blob/master/Window/Window.d#L177 I put the instances in a module global array and the module dtor finalize the data.Szymon Gatner:In my specific example I am creating OpenGL Renderer. Renderer class instance holds GLContext instance. After context creation GL objects are created like textures and vertex buffers. Those are Texture and VertexBuffer class instances too. It is critical that those child resources are freed before GL context is destroyed. Thing is, even tho Renderer keeps list of Textures , VertexBuffers and Context object, order of their destruction is completely undefined making Context d-tor called first and then child resources d-tors which ends in catastrophe. In C++ (which has a LOT of problems) this is a no-brainer. Order of d-tors is fully defined. Sub-objects are destroyed before parent d-tor is called so only thing to worry about is the order of definition of members. This is just an example but I would think that it is something rather important to have... What about child objects un-registering themselves in d-tors from a list that parent object holds and parent is destroyed first? What about asynchronous completion handler object that should notify some other object that it finished/not finished a job but a notifee is already destroyed because application is being shut-down? I honestly can't imagine how to reason about object graph lifetimes in GC world and I am sure I am missing something very basic. Probably a very different mindset.I just want them to do their cleanup first as they should.Why? Perhaps if you explain what's behind your needs better, people can help better. Bye, bearophile
Feb 27 2014
On Thursday, 27 February 2014 at 12:32:36 UTC, Namespace wrote:On Thursday, 27 February 2014 at 12:25:49 UTC, Szymon Gatner wrote:Module d-tor() looks like a pretty good solution, thanks. shared_ptr tho... I was really hoping that I am moving away from it to a better place... Still, this feels like working around a language issue, if c-tor order is defined why d-tor isn't? I am ok with non-deterministic time of execution of d-tors/finalizers but not-having parent-child d-tor order defined? That is weird.On Thursday, 27 February 2014 at 11:13:17 UTC, bearophile wrote:I had the same problem in Dgame. Therefore I use shared pointers (https://github.com/Dgame/Dgame/blob/master/Graphics/Surface.d#L90) or if I have to use classes, I use this: https://github.com/Dgame/Dgame/blob/master/Window/Window.d#L44 https://github.com/Dgame/Dgame/blob/master/Window/Window.d#L177 I put the instances in a module global array and the module dtor finalize the data.Szymon Gatner:In my specific example I am creating OpenGL Renderer. Renderer class instance holds GLContext instance. After context creation GL objects are created like textures and vertex buffers. Those are Texture and VertexBuffer class instances too. It is critical that those child resources are freed before GL context is destroyed. Thing is, even tho Renderer keeps list of Textures , VertexBuffers and Context object, order of their destruction is completely undefined making Context d-tor called first and then child resources d-tors which ends in catastrophe. In C++ (which has a LOT of problems) this is a no-brainer. Order of d-tors is fully defined. Sub-objects are destroyed before parent d-tor is called so only thing to worry about is the order of definition of members. This is just an example but I would think that it is something rather important to have... What about child objects un-registering themselves in d-tors from a list that parent object holds and parent is destroyed first? What about asynchronous completion handler object that should notify some other object that it finished/not finished a job but a notifee is already destroyed because application is being shut-down? I honestly can't imagine how to reason about object graph lifetimes in GC world and I am sure I am missing something very basic. Probably a very different mindset.I just want them to do their cleanup first as they should.Why? Perhaps if you explain what's behind your needs better, people can help better. Bye, bearophile
Feb 27 2014
On Thursday, 27 February 2014 at 13:00:27 UTC, Szymon Gatner wrote:On Thursday, 27 February 2014 at 12:32:36 UTC, Namespace wrote:I use this solution especially because I have to finalize the data before I call SDL_Quit. And therefore I cannot trust the non-deterministic execution of the Dtor.On Thursday, 27 February 2014 at 12:25:49 UTC, Szymon Gatner wrote:Module d-tor() looks like a pretty good solution, thanks. shared_ptr tho... I was really hoping that I am moving away from it to a better place... Still, this feels like working around a language issue, if c-tor order is defined why d-tor isn't? I am ok with non-deterministic time of execution of d-tors/finalizers but not-having parent-child d-tor order defined? That is weird.On Thursday, 27 February 2014 at 11:13:17 UTC, bearophile wrote:I had the same problem in Dgame. Therefore I use shared pointers (https://github.com/Dgame/Dgame/blob/master/Graphics/Surface.d#L90) or if I have to use classes, I use this: https://github.com/Dgame/Dgame/blob/master/Window/Window.d#L44 https://github.com/Dgame/Dgame/blob/master/Window/Window.d#L177 I put the instances in a module global array and the module dtor finalize the data.Szymon Gatner:In my specific example I am creating OpenGL Renderer. Renderer class instance holds GLContext instance. After context creation GL objects are created like textures and vertex buffers. Those are Texture and VertexBuffer class instances too. It is critical that those child resources are freed before GL context is destroyed. Thing is, even tho Renderer keeps list of Textures , VertexBuffers and Context object, order of their destruction is completely undefined making Context d-tor called first and then child resources d-tors which ends in catastrophe. In C++ (which has a LOT of problems) this is a no-brainer. Order of d-tors is fully defined. Sub-objects are destroyed before parent d-tor is called so only thing to worry about is the order of definition of members. This is just an example but I would think that it is something rather important to have... What about child objects un-registering themselves in d-tors from a list that parent object holds and parent is destroyed first? What about asynchronous completion handler object that should notify some other object that it finished/not finished a job but a notifee is already destroyed because application is being shut-down? I honestly can't imagine how to reason about object graph lifetimes in GC world and I am sure I am missing something very basic. Probably a very different mindset.I just want them to do their cleanup first as they should.Why? Perhaps if you explain what's behind your needs better, people can help better. Bye, bearophile
Feb 27 2014
On Thursday, 27 February 2014 at 13:04:17 UTC, Namespace wrote:I use this solution especially because I have to finalize the data before I call SDL_Quit. And therefore I cannot trust the non-deterministic execution of the Dtor.I fully understand that ;) I will take a look at DGame too for sure. Atm now I am still learning D and its abilities to directly use C code.
Feb 27 2014
On 2/27/2014 10:00 PM, Szymon Gatner wrote:Still, this feels like working around a language issue, if c-tor order is defined why d-tor isn't? I am ok with non-deterministic time of execution of d-tors/finalizers but not-having parent-child d-tor order defined? That is weird.I've never seen a garbage collected language where the GC guarantees order of destruction. There's probably a very good reason for it.
Feb 27 2014
On 2/27/2014 9:25 PM, Szymon Gatner wrote:This is just an example but I would think that it is something rather important to have... What about child objects un-registering themselves in d-tors from a list that parent object holds and parent is destroyed first? What about asynchronous completion handler object that should notify some other object that it finished/not finished a job but a notifee is already destroyed because application is being shut-down? I honestly can't imagine how to reason about object graph lifetimes in GC world and I am sure I am missing something very basic. Probably a very different mindset.Two simple rules I follow. I tend to add two methods to classes that need to do any sort of set up and clean up: initialize and terminate. Then, at app exit, I make sure that the terminate methods are called either with scope(exit) or, if I want to log any exceptions that percolate up to main, try-catch-finally. Something like this: class TextureManager { private TexContainer _loadedTextures; public void initialize() {...} public void terminate() { foreach( tex; _loadedTextures[]) tex.terminate(); } } struct Game { disable this(); disable this( this ); private static TextureManager _texMan; public static void initialize() { _texMan = new TextureManager(); _texMan.initialize(); } public static void terminate() { _texMan.terminate(); } } void main() { scope( exit ) Game.terminate(); Game.initialize(); } In some parts of a system, for objects that tend to be short lived, I'll use structs with destructors for RAII. A good example of this is for vertex and fragment shaders. The shader programs are long-lived, so those are classes, but I always destroy the shader objects as soon as any programs that need them are built. So those are perfect candidates for the struct-based RAII approach. RAII is a convenient tool, but it's just that, a tool. One of the tradeoffs you have to make with D's GC is that you can't use RAII the same way you do in C++. You *can* use it with structs, but for classes you're going to have to put C++ out of your head.
Feb 27 2014
On Thursday, 27 February 2014 at 13:07:37 UTC, Mike Parker wrote:On 2/27/2014 9:25 PM, Szymon Gatner wrote:Then the question is why not use structs all the time? After using D for a bit more as a week I come to the solution that looks like this. strict WasAClassInCpp { disable this(); //sadly we can not use ctor in D like in C++ :( disable this(this); //this is not a copy constructor, this is something called after all the data in the struct was copied... ~this(){ ... } //dtor, just like in C++ } So all my classes in C++ are ported to D structs. I was using class only to port abstract class from C++. Replacing it by inerface.This is just an example but I would think that it is something rather important to have... What about child objects un-registering themselves in d-tors from a list that parent object holds and parent is destroyed first? What about asynchronous completion handler object that should notify some other object that it finished/not finished a job but a notifee is already destroyed because application is being shut-down? I honestly can't imagine how to reason about object graph lifetimes in GC world and I am sure I am missing something very basic. Probably a very different mindset.Two simple rules I follow. resources I tend to add two methods to classes that need to do any sort of set up and clean up: initialize and terminate. Then, at app exit, I make sure that the terminate methods are called either with scope(exit) or, if I want to log any exceptions that percolate up to main, try-catch-finally. Something like this: class TextureManager { private TexContainer _loadedTextures; public void initialize() {...} public void terminate() { foreach( tex; _loadedTextures[]) tex.terminate(); } } struct Game { disable this(); disable this( this ); private static TextureManager _texMan; public static void initialize() { _texMan = new TextureManager(); _texMan.initialize(); } public static void terminate() { _texMan.terminate(); } } void main() { scope( exit ) Game.terminate(); Game.initialize(); } In some parts of a system, for objects that tend to be short lived, I'll use structs with destructors for RAII. A good example of this is for vertex and fragment shaders. The shader programs are long-lived, so those are classes, but I always destroy the shader objects as soon as any programs that need them are built. So those are perfect candidates for the struct-based RAII approach. RAII is a convenient tool, but it's just that, a tool. One of the tradeoffs you have to make with D's GC is that you can't use RAII the same way you do in C++. You *can* use it with structs, but for classes you're going to have to put C++ out of your head.
Feb 27 2014
On Thursday, 27 February 2014 at 13:18:51 UTC, Remo wrote:Then the question is why not use structs all the time?Key class feature is run-time polymorphism (via interfaces/inheritance). I tend to use structs for everything else in my personal code.
Feb 27 2014
On Thursday, 27 February 2014 at 13:31:45 UTC, Dicebot wrote:On Thursday, 27 February 2014 at 13:18:51 UTC, Remo wrote:Maybe we really should implement ARC classes... :)Then the question is why not use structs all the time?Key class feature is run-time polymorphism (via interfaces/inheritance). I tend to use structs for everything else in my personal code.
Feb 27 2014
On Thursday, 27 February 2014 at 13:44:11 UTC, Namespace wrote:On Thursday, 27 February 2014 at 13:31:45 UTC, Dicebot wrote:I don't see how it is relevant. I would not have used ARC classes either.On Thursday, 27 February 2014 at 13:18:51 UTC, Remo wrote:Maybe we really should implement ARC classes... :)Then the question is why not use structs all the time?Key class feature is run-time polymorphism (via interfaces/inheritance). I tend to use structs for everything else in my personal code.
Feb 27 2014
On Thursday, 27 February 2014 at 14:12:58 UTC, Dicebot wrote:On Thursday, 27 February 2014 at 13:44:11 UTC, Namespace wrote:Why not? Overhead? No RAII support?On Thursday, 27 February 2014 at 13:31:45 UTC, Dicebot wrote:I don't see how it is relevant. I would not have used ARC classes either.On Thursday, 27 February 2014 at 13:18:51 UTC, Remo wrote:Maybe we really should implement ARC classes... :)Then the question is why not use structs all the time?Key class feature is run-time polymorphism (via interfaces/inheritance). I tend to use structs for everything else in my personal code.
Feb 27 2014
On Thursday, 27 February 2014 at 14:14:43 UTC, Namespace wrote:Why not? Overhead? No RAII support?Simply no reason to use classes, structs have all features I need for cases when polymorphism is not necessary (95%+). Being value type is also convenient as it leaves more control to the programmer and RAII is nice cherry on top.
Feb 27 2014
On Thursday, 27 February 2014 at 14:18:47 UTC, Dicebot wrote:On Thursday, 27 February 2014 at 14:14:43 UTC, Namespace wrote:They actually don't have all the necessary features in D afaiu. They do have value semantics but can't represent uniqueness because of missing move d-tor. For example in C++ I can create a function that returns a Texture class instance and be sure that it is the only one when receiving it (because copying is disabled). Then I can always safely release all resources related to this texture in objects d-tor. In D I can't use struct for this because I would get double-free in d-tor so a class instance has to be used instead.Why not? Overhead? No RAII support?Simply no reason to use classes, structs have all features I need for cases when polymorphism is not necessary (95%+). Being value type is also convenient as it leaves more control to the programmer and RAII is nice cherry on top.
Feb 27 2014
On Thursday, 27 February 2014 at 14:37:14 UTC, Szymon Gatner wrote:They actually don't have all the necessary features in D afaiu. They do have value semantics but can't represent uniqueness because of missing move d-tor. For example in C++ I can create a function that returns a Texture class instance and be sure that it is the only one when receiving it (because copying is disabled). Then I can always safely release all resources related to this texture in objects d-tor. In D I can't use struct for this because I would get double-free in d-tor so a class instance has to be used instead.You can disable postblit to make entity non-copyable: http://dlang.org/struct.html#StructPostblit
Feb 27 2014
There is also one complex and feature-reach implementation of uniqueness concept by Sonke Ludwig : https://github.com/rejectedsoftware/vibe.d/blob/master/source/vibe/cor /concurrency.d#L281 (Isolated!T) Priceless for message passing concurrency.
Feb 27 2014
On Thursday, 27 February 2014 at 14:42:43 UTC, Dicebot wrote:There is also one complex and feature-reach implementation of uniqueness concept by Sonke Ludwig : https://github.com/rejectedsoftware/vibe.d/blob/master/source/vibe/cor /concurrency.d#L281 (Isolated!T) Priceless for message passing concurrency.Tbh it only looks worse and worse to me :( Another example of code necessary to overcome language limitations.
Feb 27 2014
On Thursday, 27 February 2014 at 14:52:00 UTC, Szymon Gatner wrote:On Thursday, 27 February 2014 at 14:42:43 UTC, Dicebot wrote:Do you know Rust? http://www.rust-lang.org/There is also one complex and feature-reach implementation of uniqueness concept by Sonke Ludwig : https://github.com/rejectedsoftware/vibe.d/blob/master/source/vibe/cor /concurrency.d#L281 (Isolated!T) Priceless for message passing concurrency.Tbh it only looks worse and worse to me :( Another example of code necessary to overcome language limitations.
Feb 27 2014
On Thursday, 27 February 2014 at 14:56:22 UTC, Namespace wrote:On Thursday, 27 February 2014 at 14:52:00 UTC, Szymon Gatner wrote:I do. Do you want me to go away? ;)On Thursday, 27 February 2014 at 14:42:43 UTC, Dicebot wrote:Do you know Rust? http://www.rust-lang.org/There is also one complex and feature-reach implementation of uniqueness concept by Sonke Ludwig : https://github.com/rejectedsoftware/vibe.d/blob/master/source/vibe/cor /concurrency.d#L281 (Isolated!T) Priceless for message passing concurrency.Tbh it only looks worse and worse to me :( Another example of code necessary to overcome language limitations.
Feb 27 2014
On Thursday, 27 February 2014 at 15:09:39 UTC, Szymon Gatner wrote:On Thursday, 27 February 2014 at 14:56:22 UTC, Namespace wrote:No ;) But maybe Rust has your needed features. ;) If you want to stay at D, you can use the shared and unique pointer of Dgame.Internal if you want.On Thursday, 27 February 2014 at 14:52:00 UTC, Szymon Gatner wrote:I do. Do you want me to go away? ;)On Thursday, 27 February 2014 at 14:42:43 UTC, Dicebot wrote:Do you know Rust? http://www.rust-lang.org/There is also one complex and feature-reach implementation of uniqueness concept by Sonke Ludwig : https://github.com/rejectedsoftware/vibe.d/blob/master/source/vibe/cor /concurrency.d#L281 (Isolated!T) Priceless for message passing concurrency.Tbh it only looks worse and worse to me :( Another example of code necessary to overcome language limitations.
Feb 27 2014
On Thursday, 27 February 2014 at 15:09:39 UTC, Szymon Gatner wrote:On Thursday, 27 February 2014 at 14:56:22 UTC, Namespace wrote:I have looked at Rust and Go but I still prefer D2 :) D2 CTFE, templates and mixin are great. Another advantage of D is the 'easy' porting from C and C++. But this problems with structs and classes... I am also missing Rvalue references (move semantics) from C++11.On Thursday, 27 February 2014 at 14:52:00 UTC, Szymon Gatner wrote:I do. Do you want me to go away? ;)On Thursday, 27 February 2014 at 14:42:43 UTC, Dicebot wrote:Do you know Rust? http://www.rust-lang.org/There is also one complex and feature-reach implementation of uniqueness concept by Sonke Ludwig : https://github.com/rejectedsoftware/vibe.d/blob/master/source/vibe/cor /concurrency.d#L281 (Isolated!T) Priceless for message passing concurrency.Tbh it only looks worse and worse to me :( Another example of code necessary to overcome language limitations.
Feb 27 2014
Szymon Gatner:Tbh it only looks worse and worse to me :(Perhaps for your use case it's better for you to stick with C++11? While I have written a good amount of D code (perhaps 200_000 lines or more), I still use Python a lot, etc. Bye, bearophile
Feb 27 2014
On Thursday, 27 February 2014 at 14:58:50 UTC, bearophile wrote:Szymon Gatner:For now I don'r really see alternative. Isn't resource a management a crucial part of everyday programming? Or is it really just me? I do use Python for simple tools and work mainly in C++11(ish as it is really just Microsoft's dialect). Thing is, I really want to use D. I want "Modern convenience", "Modeling power" and "Native efficiency". I want to feel like home wrt to syntax and at the same time I want for some problems to just go away. I think I am just not getting something being so deeply rooted in C++.Tbh it only looks worse and worse to me :(Perhaps for your use case it's better for you to stick with C++11? While I have written a good amount of D code (perhaps 200_000 lines or more), I still use Python a lot, etc.
Feb 27 2014
On Thursday, 27 February 2014 at 15:15:06 UTC, Szymon Gatner wrote:On Thursday, 27 February 2014 at 14:58:50 UTC, bearophile wrote:Resource management is important part, but part but not every language handles it the same way. Apparently some peoples prefers that the language do almost all of this by it self no mater how bad/slow it is.Szymon Gatner:For now I don'r really see alternative. Isn't resource a management a crucial part of everyday programming? Or is it really just me?Tbh it only looks worse and worse to me :(Perhaps for your use case it's better for you to stick with C++11? While I have written a good amount of D code (perhaps 200_000 lines or more), I still use Python a lot, etc.I do use Python for simple tools and work mainly in C++11(ish as it is really just Microsoft's dialect).What do you mean by Microsoft's dialect?
Feb 27 2014
On Thursday, 27 February 2014 at 15:36:02 UTC, Remo wrote:What do you mean by Microsoft's dialect?I mean half-implemented buggy version of C++11 in VC2012 ;)
Feb 27 2014
On Thursday, 27 February 2014 at 15:39:48 UTC, Szymon Gatner wrote:On Thursday, 27 February 2014 at 15:36:02 UTC, Remo wrote:Or in VC2013, but if you can use Intel compiler then it is better.What do you mean by Microsoft's dialect?I mean half-implemented buggy version of C++11 in VC2012 ;)
Feb 27 2014
On Thursday, 27 February 2014 at 15:56:26 UTC, Remo wrote:On Thursday, 27 February 2014 at 15:39:48 UTC, Szymon Gatner wrote:VC2013 at least has variadics... I will not spend another 400 bucks just for that tho, and only a year after previous release. But that is OT ;)On Thursday, 27 February 2014 at 15:36:02 UTC, Remo wrote:Or in VC2013, but if you can use Intel compiler then it is better.What do you mean by Microsoft's dialect?I mean half-implemented buggy version of C++11 in VC2012 ;)
Feb 27 2014
On Thursday, 27 February 2014 at 14:52:00 UTC, Szymon Gatner wrote:On Thursday, 27 February 2014 at 14:42:43 UTC, Dicebot wrote:Or, alternatively: A language flexible enough to facilitate library solutions for problems that would normally require explicit language support.There is also one complex and feature-reach implementation of uniqueness concept by Sonke Ludwig : https://github.com/rejectedsoftware/vibe.d/blob/master/source/vibe/cor /concurrency.d#L281 (Isolated!T) Priceless for message passing concurrency.Tbh it only looks worse and worse to me :( Another example of code necessary to overcome language limitations.
Feb 27 2014
On Thursday, 27 February 2014 at 18:06:58 UTC, John Colvin wrote:On Thursday, 27 February 2014 at 14:52:00 UTC, Szymon Gatner wrote:I dig flexibility, I really do, and I appreciate D's features that enable that, but in case of such basic thing as a resource management, I just want things to work without surprises by default.On Thursday, 27 February 2014 at 14:42:43 UTC, Dicebot wrote:Or, alternatively: A language flexible enough to facilitate library solutions for problems that would normally require explicit language support.There is also one complex and feature-reach implementation of uniqueness concept by Sonke Ludwig : https://github.com/rejectedsoftware/vibe.d/blob/master/source/vibe/cor /concurrency.d#L281 (Isolated!T) Priceless for message passing concurrency.Tbh it only looks worse and worse to me :( Another example of code necessary to overcome language limitations.
Feb 27 2014
On Thursday, 27 February 2014 at 18:29:57 UTC, Szymon Gatner wrote:I dig flexibility, I really do, and I appreciate D's features that enable that, but in case of such basic thing as a resource management, I just want things to work without surprises by default.Resource management (including memory management) is on of most complicated areas in programming. I can call it anything but basic.
Feb 28 2014
On Friday, 28 February 2014 at 10:44:22 UTC, Dicebot wrote:On Thursday, 27 February 2014 at 18:29:57 UTC, Szymon Gatner wrote:I didn't mean "basic" in the sense of "easy" but in the sense of something that has to dealt with all the time / is common requirement. "Programs == Algorithms + Data structures" great man once said. D is pretty damn good at algorithms part, better than C++ thanks to ranges (zero cost composability codegen issues aside) but data strucutres... I wish I felt the same way about them. Is it really so much to ask for? That child's finalizers are called before parent finalizer (assuming no circular refs, then again there are no weak class refst in D right)? Parent holds references to them for crying out loud... Why is that not the default and obvious behaviour? Is that a limitation imposed by GC somehow? My understanding is that GC has to scan from root to leaves so it knows the structure exactly anyway, why not just generate finalizer call list when traversing?I dig flexibility, I really do, and I appreciate D's features that enable that, but in case of such basic thing as a resource management, I just want things to work without surprises by default.Resource management (including memory management) is on of most complicated areas in programming. I can call it anything but basic.
Feb 28 2014
On Friday, 28 February 2014 at 11:28:01 UTC, Szymon Gatner wrote:I didn't mean "basic" in the sense of "easy" but in the sense of something that has to dealt with all the time / is common requirement.Yes, it needs to be dealt with all the time but in a different ways. Problem is with getting sensible defaults. D makes a reasonable assumption that most applications don't actually care about tight bullet-proof resource management and defaults to GC. I may not like it but it fits criteria "built-in resource management" and pretty much shows that it is not as basic as one may think."Programs == Algorithms + Data structures" great man once said. D is pretty damn good at algorithms part, better than C++ thanks to ranges (zero cost composability codegen issues aside) but data strucutres... I wish I felt the same way about them.Most problems I have with D data structures come from qualifiers, not from resource management. I really don't understand why this looks that much of a problem. That said, my background very influenced by plain C and that results in different habits and expectations.Is that a limitation imposed by GC somehow? My understanding is that GC has to scan from root to leaves so it knows the structure exactly anyway, why not just generate finalizer call list when traversing?Can't tell because of my very limited knowledge about GC internals. In practice I don't care because I never ever want to interfere with GC resource mangement - stuff that I want to micro-managed is allocated from custom pools and thus is not a subject to unexpected destructor calls.
Feb 28 2014
On 2/28/2014 8:43 PM, Dicebot wrote:Most problems I have with D data structures come from qualifiers, not from resource management. I really don't understand why this looks that much of a problem. That said, my background very influenced by plain C and that results in different habits and expectations.I have a strong C background as well and have never had any complaints about resource management in D. Every complaint I've seen has come from people trying to do C++-like RAII. And, though I don't understand it either, it does seem to be a big issue for them.
Feb 28 2014
On Friday, 28 February 2014 at 11:54:52 UTC, Mike Parker wrote:On 2/28/2014 8:43 PM, Dicebot wrote:It really is, RAII is the most important idiom in C++, in short no RAII == buggy code. I mean proper C++ not C-with-classes-no-templates-no-exceptions bs. So to sum up: C folks are not really happy, C++ folks are notMost problems I have with D data structures come from qualifiers, not from resource management. I really don't understand why this looks that much of a problem. That said, my background very influenced by plain C and that results in different habits and expectations.I have a strong C background as well and have never had any complaints about resource management in D. Every complaint I've seen has come from people trying to do C++-like RAII. And, though I don't understand it either, it does seem to be a big issue for them.
Feb 28 2014
On Friday, 28 February 2014 at 12:15:21 UTC, Szymon Gatner wrote:It really is, RAII is the most important idiom in C++, in short no RAII == buggy code. I mean proper C++ not C-with-classes-no-templates-no-exceptions bs. So to sum up: C folks are not really happy, C++ folks are notRepeating this again and again - you can use RAII. Just not with GC. It is importan idiom and it is supported. But it is not "one true way" so it is not supported for everything.
Feb 28 2014
On Friday, 28 February 2014 at 12:17:22 UTC, Dicebot wrote:On Friday, 28 February 2014 at 12:15:21 UTC, Szymon Gatner wrote:I know I can, my point is that it is more difficult and I don't like it ;)It really is, RAII is the most important idiom in C++, in short no RAII == buggy code. I mean proper C++ not C-with-classes-no-templates-no-exceptions bs. So to sum up: C folks are not really happy, C++ folks are notRepeating this again and again - you can use RAII. Just not with GC. It is importan idiom and it is supported. But it is not "one true way" so it is not supported for everything.
Feb 28 2014
On 2/28/2014 9:15 PM, Szymon Gatner wrote:So to sum up: C folks are not really happy, C++ folks are not reallyI'm a C folk and I'm really happy :)
Feb 28 2014
On Friday, 28 February 2014 at 12:48:47 UTC, Mike Parker wrote:On 2/28/2014 9:15 PM, Szymon Gatner wrote:C'mon, GC has to be an itch for you mallocers :) Come to the dark side...So to sum up: C folks are not really happy, C++ folks are not reallyI'm a C folk and I'm really happy :)
Feb 28 2014
On Friday, 28 February 2014 at 12:52:28 UTC, Szymon Gatner wrote:+1I'm a C folk and I'm really happy :)C'mon, GC has to be an itch for you mallocers :) Come to the dark side...It sometimes is. In that case we don't use GC. Don't get me wrong - there are issues with current GC enforcement and it is a major problem for real-time applications, there are lot of threads with debates on topic (with me acting on against-the-GC side). But it is a very small subset of applications most programmers will never even write once in their life, for everything else existing tools are pretty good. I really think it is more of C++ architectural habit that itches you right now :)
Feb 28 2014
On Friday, 28 February 2014 at 11:43:58 UTC, Dicebot wrote:On Friday, 28 February 2014 at 11:28:01 UTC, Szymon Gatner wrote:Not really different tho. Actual function call swqence might be different but the scheme is always the same: acquire resource, allocate, connect, take from pool vs release, deallocate, disconnect, return to pool. All of those fall under resource management - there is a finite amout of a resouce whether it is a memory, a system process, a file or a databese connection and it is crucial to the system stability that all of them are properly returned / released AND in proper order (which is of course reverse to "acquisition").I didn't mean "basic" in the sense of "easy" but in the sense of something that has to dealt with all the time / is common requirement.Yes, it needs to be dealt with all the time but in a different ways. Problem is with getting sensible defaults. D makes a reasonable assumption that most applications don't actually care about tight bullet-proof resource management and defaults to GC. I may not like it but it fits criteria "built-in resource management" and pretty much shows that it is not as basic as one may think.
Feb 28 2014
Le 28/02/2014 13:22, Szymon Gatner a écrit :On Friday, 28 February 2014 at 11:43:58 UTC, Dicebot wrote:I had a lot of difficulties too with the release order of resources. Of course I am coming from c++, in which it's to ease to manage. I got some head-hack for the resource management, maybe a DIP must be done here about a module dedicated to the resource management? Or at least a tutorial in the wiki? I finally solve my issues, but I am not happy, cause the way it's done seems to be too much error prone (resource leaks). I used to work on mobile devices and some kind of resources have to be released as soon as possible. I also don't really like having a lot of applications running on devices never releasing resources, it can break applications at the same time, you'll have to buy more memory.On Friday, 28 February 2014 at 11:28:01 UTC, Szymon Gatner wrote:Not really different tho. Actual function call swqence might be different but the scheme is always the same: acquire resource, allocate, connect, take from pool vs release, deallocate, disconnect, return to pool. All of those fall under resource management - there is a finite amout of a resouce whether it is a memory, a system process, a file or a databese connection and it is crucial to the system stability that all of them are properly returned / released AND in proper order (which is of course reverse to "acquisition").I didn't mean "basic" in the sense of "easy" but in the sense of something that has to dealt with all the time / is common requirement.Yes, it needs to be dealt with all the time but in a different ways. Problem is with getting sensible defaults. D makes a reasonable assumption that most applications don't actually care about tight bullet-proof resource management and defaults to GC. I may not like it but it fits criteria "built-in resource management" and pretty much shows that it is not as basic as one may think.
Feb 28 2014
On Thu, 27 Feb 2014 18:29:55 -0000, Szymon Gatner <noemail gmail.com> wrote:On Thursday, 27 February 2014 at 18:06:58 UTC, John Colvin wrote:Amen. (Not used religiously) I have been around D for a long time, and I have noticed a growing trend of solving problems with "clever" but complicated library solutions when in *some* cases a simpler built-in solution was possible. I realise Walter's time is precious and I realise that adding complexity to the language itself is something to be generally avoided, but I think sometimes we make the wrong choice. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/On Thursday, 27 February 2014 at 14:52:00 UTC, Szymon Gatner wrote:I dig flexibility, I really do, and I appreciate D's features that enable that, but in case of such basic thing as a resource management, I just want things to work without surprises by default.On Thursday, 27 February 2014 at 14:42:43 UTC, Dicebot wrote:Or, alternatively: A language flexible enough to facilitate library solutions for problems that would normally require explicit language support.There is also one complex and feature-reach implementation of uniqueness concept by Sonke Ludwig : https://github.com/rejectedsoftware/vibe.d/blob/master/source/vibe/cor /concurrency.d#L281 (Isolated!T) Priceless for message passing concurrency.Tbh it only looks worse and worse to me :( Another example of code necessary to overcome language limitations.
Feb 28 2014
On Friday, 28 February 2014 at 10:45:53 UTC, Regan Heath wrote:On Thu, 27 Feb 2014 18:29:55 -0000, Szymon Gatner <noemail gmail.com> wrote:Yeah scope -> scoped is IMO such a wrong choice. :)On Thursday, 27 February 2014 at 18:06:58 UTC, John Colvin wrote:Amen. (Not used religiously) I have been around D for a long time, and I have noticed a growing trend of solving problems with "clever" but complicated library solutions when in *some* cases a simpler built-in solution was possible. I realise Walter's time is precious and I realise that adding complexity to the language itself is something to be generally avoided, but I think sometimes we make the wrong choice. ROn Thursday, 27 February 2014 at 14:52:00 UTC, Szymon Gatner wrote:I dig flexibility, I really do, and I appreciate D's features that enable that, but in case of such basic thing as a resource management, I just want things to work without surprises by default.On Thursday, 27 February 2014 at 14:42:43 UTC, Dicebot wrote:Or, alternatively: A language flexible enough to facilitate library solutions for problems that would normally require explicit language support.There is also one complex and feature-reach implementation of uniqueness concept by Sonke Ludwig : https://github.com/rejectedsoftware/vibe.d/blob/master/source/vibe/cor /concurrency.d#L281 (Isolated!T) Priceless for message passing concurrency.Tbh it only looks worse and worse to me :( Another example of code necessary to overcome language limitations.
Feb 28 2014
On Thursday, 27 February 2014 at 14:41:27 UTC, Dicebot wrote:On Thursday, 27 February 2014 at 14:37:14 UTC, Szymon Gatner wrote:How can I then use it as a function return value? Or store in a container? Actually if postblit had a bool param saying that the source is rvalue then moving would be possible by just resetting relevant fields in source object.They actually don't have all the necessary features in D afaiu. They do have value semantics but can't represent uniqueness because of missing move d-tor. For example in C++ I can create a function that returns a Texture class instance and be sure that it is the only one when receiving it (because copying is disabled). Then I can always safely release all resources related to this texture in objects d-tor. In D I can't use struct for this because I would get double-free in d-tor so a class instance has to be used instead.You can disable postblit to make entity non-copyable: http://dlang.org/struct.html#StructPostblit
Feb 27 2014
On Thursday, 27 February 2014 at 14:49:48 UTC, Szymon Gatner wrote:Yep, moving ownership is the main issue (as opposed to just prohibiting any copy). But returning from function is not copying because of D semantics and you can do some tricks because of it: http://dpaste.dzfl.pl/99ca668a1a8d ================================== import std.c.stdlib; struct Unique { int* data; disable this(this); ~this() { if (data) free(data); } Unique release() { scope(exit) this.data = null; return Unique(data); } } void main() { Unique x1 = Unique(cast(int*) malloc(int.sizeof)); // auto x2 = x1; // error auto x2 = x1.release(); assert(x1.data is null); assert(x2.data !is null); }You can disable postblit to make entity non-copyable: http://dlang.org/struct.html#StructPostblitHow can I then use it as a function return value? Or store in a container? Actually if postblit had a bool param saying that the source is rvalue then moving would be possible by just resetting relevant fields in source object.
Feb 27 2014
On Thursday, 27 February 2014 at 14:37:14 UTC, Szymon Gatner wrote:They actually don't have all the necessary features in D afaiu. They do have value semantics but can't represent uniqueness because of missing move d-tor.struct MovingStruct { disable this(this); typeof(this) release() { auto p = this.payload; this.payload = null; return typeof(this)(p); } } That does moving via an explicit release call which is statically forced upon you by the disabled copy. MovingStruct s = some_payload; // MovingStruct s2 = s; // compile error MovingStruct s2 = s.release; assert(s.payload is null); // passes assert(s2.payload is some_payload); // we good You can also easily do structs with reference semantics: struct RefStruct { private struct Impl { // implementation here } Impl* payload; alias payload this; } RefStruct is now just a thin wrapper over a pointer and thus inherits the pointer's semantics. You can add a destructor to RefStruct to free it deterministically with RAII as well. To avoid double free, you can use the move technique or refcounting: struct RefCountingStruct { private struct Impl { // implementation here int refcount; } Impl* payload; alias payload this; disable this(); // disable default constructor to force factory static RefCountingStruct create() { RefCountingStruct t = void; t.payload = new Impl(); t.payload.refcount = 1; return t; } this(this) { if(payload !is null) payload.refcount++; } ~this() { if(payload !is null) { payload.refcount--; if(payload.refcount == 0) whatever_free(payload); } } } i wish my book was out but it is still only half done... but i wrote a chapter with like eight different struct tricks like this. structs rock.
Feb 27 2014
On Thursday, 27 February 2014 at 16:10:34 UTC, Adam D. Ruppe wrote:On Thursday, 27 February 2014 at 14:37:14 UTC, Szymon Gatner wrote:Wow, that is pretty great stuff. Bit verbose, but gets the job done. Is there a way to factor it out for reuse? As a mixin probably? Thanks! Will surely try this. And I want your book.They actually don't have all the necessary features in D afaiu. They do have value semantics but can't represent uniqueness because of missing move d-tor.struct MovingStruct { disable this(this); typeof(this) release() { auto p = this.payload; this.payload = null; return typeof(this)(p); } } That does moving via an explicit release call which is statically forced upon you by the disabled copy. MovingStruct s = some_payload; // MovingStruct s2 = s; // compile error MovingStruct s2 = s.release; assert(s.payload is null); // passes assert(s2.payload is some_payload); // we good You can also easily do structs with reference semantics: struct RefStruct { private struct Impl { // implementation here } Impl* payload; alias payload this; } RefStruct is now just a thin wrapper over a pointer and thus inherits the pointer's semantics. You can add a destructor to RefStruct to free it deterministically with RAII as well. To avoid double free, you can use the move technique or refcounting: struct RefCountingStruct { private struct Impl { // implementation here int refcount; } Impl* payload; alias payload this; disable this(); // disable default constructor to force factory static RefCountingStruct create() { RefCountingStruct t = void; t.payload = new Impl(); t.payload.refcount = 1; return t; } this(this) { if(payload !is null) payload.refcount++; } ~this() { if(payload !is null) { payload.refcount--; if(payload.refcount == 0) whatever_free(payload); } } } i wish my book was out but it is still only half done... but i wrote a chapter with like eight different struct tricks like this. structs rock.
Feb 27 2014
On Thursday, 27 February 2014 at 16:10:34 UTC, Adam D. Ruppe wrote:struct RefCountingStruct { private struct Impl { // implementation here int refcount; } Impl* payload; alias payload this;Isn't it exactly what Phobos RefCounted does?
Feb 27 2014
On Thursday, 27 February 2014 at 17:31:57 UTC, Dicebot wrote:Isn't it exactly what Phobos RefCounted does?Yes, though knowing how the implementation works is good for stuff like interfacing with C where you might need different acquire/free/add count/release functions than phobos uses. http://dlang.org/phobos/std_typecons.html#RefCounted It always uses malloc and free, which isn't always (actually, in my cases, is rarely ever) what you want. It is (obviously) possible to write a generic one that takes aliases (or delegates if you want all refcounted things to have the same parent type regardless of allocation strategy) for these functions, I've done that somewhere on the ng or my http server before too, but phobos doesn't do that either. The phobos one also doesn't let you wrap classes which is sometimes useful.
Feb 27 2014
On Thursday, 27 February 2014 at 13:31:45 UTC, Dicebot wrote:On Thursday, 27 February 2014 at 13:18:51 UTC, Remo wrote:That is very similar to my thoughts atm. Explicit call to init() / terminate() are so C :/ It really seems that there is no escape from value semantics and shared_ptr. Worst part is there is no even standard shared/weak pointer provided. I must say I am kindof disappointed by all this. I realize that it is not D's fault but still, it is suppose to be "better C++", and while I do see that wrt to templates / TMP, my favourite feature of C++ are d-tors...Then the question is why not use structs all the time?Key class feature is run-time polymorphism (via interfaces/inheritance). I tend to use structs for everything else in my personal code.
Feb 27 2014
On Thursday, 27 February 2014 at 14:29:05 UTC, Szymon Gatner wrote:Explicit call to init() / terminate() are so C :/It is much better than C because of `scope(exit) terminate()` though :) Also you can use struct destructors same as in C++Worst part is there is no even standard shared/weak pointer provided.which helps in some cases.I must say I am kindof disappointed by all this. I realize that it is not D's fault but still, it is suppose to be "better C++", and while I do see that wrt to templates / TMP, my favourite feature of C++ are d-tors...It is not supposed to be "better C++", not anymore at least. Something that dissapoints lot of people and there has been a lot of pushing in this direction lately but historically this domain was under-developed.
Feb 27 2014