digitalmars.D.learn - How to write a proper class destructor?
- Bradley Smith (8/8) Jan 24 2007 According to the documentation, a class destructor is "expected to
- kris (4/18) Jan 25 2007 Yeah, that's a good one :)
- Bradley Smith (5/25) Jan 25 2007 Isn't the destructor behavior dictated by the language? How can it be
- Frits van Bommel (5/25) Jan 25 2007 *Behavior* is dictated by the language, yes. But the *order* in which
- kris (2/30) Jan 25 2007 Aye -- tango has a modified GC with all kinds of goodies.
- Jarrett Billingsley (26/32) Jan 25 2007 Huuaaaahhh!
- Bradley Smith (10/51) Jan 25 2007 Is scope a valid modifier for a data member? The documentation states
- Frits van Bommel (4/21) Jan 25 2007 I think he's saying that it can be fixed by modifying the GC (which
- Kevin Bealer (40/51) Jan 28 2007 Some cases like closing a socket or a file opened with the unix open(2)
- Kevin Bealer (3/3) Jan 28 2007 Just an addendum to my previous reply - the technique I mention can also...
- Jonas Kivi (27/60) Jan 26 2007 Hmm, I think I've run into this problem just a few days ago, as my own
- Frits van Bommel (8/11) Jan 26 2007 "scope" is for automatic deletion. "auto" is for type inference.
- Jarrett Billingsley (17/21) Jan 26 2007 No ;)
- Frits van Bommel (5/29) Jan 26 2007 Right, forgot about all that for a moment[1]. However, that is how it
- Jonas Kivi (6/18) Jan 26 2007 Ahh, thanks for clearing that up. I changed all the auto-keywords in my
- Frits van Bommel (5/25) Jan 26 2007 Well, one way to make sure a class never gets GC'ed is to make it a
According to the documentation, a class destructor is "expected to release any resources held by the object."[1] However, if resources to be released are in objects to be garbage collected, "those references are no longer valid."[1] How is a class supposed to release something for which it no longer has a valid reference? Bradley [1] http://www.digitalmars.com/d/class.html#destructors.
Jan 24 2007
Bradley Smith wrote:According to the documentation, a class destructor is "expected to release any resources held by the object."[1] However, if resources to be released are in objects to be garbage collected, "those references are no longer valid."[1] How is a class supposed to release something for which it no longer has a valid reference? Bradley [1] http://www.digitalmars.com/d/class.html#destructors.Yeah, that's a good one :) Tango has a good resolution for this, that stemmed from long discussion on the NG. Those changes never made it into phobos, IIRC
Jan 25 2007
kris wrote:Bradley Smith wrote:Isn't the destructor behavior dictated by the language? How can it be fixed with a library? Replace or bypass the GC? Thanks, BradleyAccording to the documentation, a class destructor is "expected to release any resources held by the object."[1] However, if resources to be released are in objects to be garbage collected, "those references are no longer valid."[1] How is a class supposed to release something for which it no longer has a valid reference? Bradley [1] http://www.digitalmars.com/d/class.html#destructors.Yeah, that's a good one :) Tango has a good resolution for this, that stemmed from long discussion on the NG. Those changes never made it into phobos, IIRC
Jan 25 2007
Bradley Smith wrote:kris wrote:*Behavior* is dictated by the language, yes. But the *order* in which they're invoked is determined by the library (specifically, the GC) and the program (if 'delete' is used). So yes, this may be fixable by replacing the GC.Bradley Smith wrote:Isn't the destructor behavior dictated by the language? How can it be fixed with a library? Replace or bypass the GC?According to the documentation, a class destructor is "expected to release any resources held by the object."[1] However, if resources to be released are in objects to be garbage collected, "those references are no longer valid."[1] How is a class supposed to release something for which it no longer has a valid reference? [1] http://www.digitalmars.com/d/class.html#destructors.Yeah, that's a good one :) Tango has a good resolution for this, that stemmed from long discussion on the NG. Those changes never made it into phobos, IIRC
Jan 25 2007
Bradley Smith wrote:kris wrote:Aye -- tango has a modified GC with all kinds of goodies.Bradley Smith wrote:Isn't the destructor behavior dictated by the language? How can it be fixed with a library? Replace or bypass the GC?According to the documentation, a class destructor is "expected to release any resources held by the object."[1] However, if resources to be released are in objects to be garbage collected, "those references are no longer valid."[1] How is a class supposed to release something for which it no longer has a valid reference? Bradley [1] http://www.digitalmars.com/d/class.html#destructors.Yeah, that's a good one :) Tango has a good resolution for this, that stemmed from long discussion on the NG. Those changes never made it into phobos, IIRC
Jan 25 2007
"Bradley Smith" <digitalmars-com baysmith.com> wrote in message news:ep9joi$1mr2$1 digitaldaemon.com...According to the documentation, a class destructor is "expected to release any resources held by the object."[1] However, if resources to be released are in objects to be garbage collected, "those references are no longer valid."[1] How is a class supposed to release something for which it no longer has a valid reference?Huuaaaahhh! I remember someone suggesting that 'scope' be a valid modifier for class instance variables, and it'd basically mean "when this class gets destroyed, destroy this other instance as well." Like auto-deletion when you use a scope reference in a function: class ResourceHolder { scope SomeResource mRsrc; this(char[] name) { mRsrc = new SomeResource(name); } } .. { scope holder = new ResourceHolder("a.file"); ... } // holder is destroyed here, and so is its mRsrc member. Another solution would be to change the behavior of the GC so that deletion on program end _is_ deterministic. That is, it'd basically run a collection sweep, call finalizers on objects which don't have references to them, and keep doing that until nothing is left. That way, references to other classes would always be valid in destructors, since the GC wouldn't collect those references until everything that points to them is destroyed.
Jan 25 2007
Jarrett Billingsley wrote:"Bradley Smith" <digitalmars-com baysmith.com> wrote in message news:ep9joi$1mr2$1 digitaldaemon.com...Is scope a valid modifier for a data member? The documentation states "scope cannot be applied to globals, statics, data members, inout or out parameters".[2] In my tests, using scope on a data member compiles, but doesn't change the behavior.According to the documentation, a class destructor is "expected to release any resources held by the object."[1] However, if resources to be released are in objects to be garbage collected, "those references are no longer valid."[1] How is a class supposed to release something for which it no longer has a valid reference?Huuaaaahhh! I remember someone suggesting that 'scope' be a valid modifier for class instance variables, and it'd basically mean "when this class gets destroyed, destroy this other instance as well." Like auto-deletion when you use a scope reference in a function:class ResourceHolder { scope SomeResource mRsrc; this(char[] name) { mRsrc = new SomeResource(name); } } .. { scope holder = new ResourceHolder("a.file"); ... } // holder is destroyed here, and so is its mRsrc member. Another solution would be to change the behavior of the GC so that deletion on program end _is_ deterministic. That is, it'd basically run a collection sweep, call finalizers on objects which don't have references to them, and keep doing that until nothing is left. That way, references to other classes would always be valid in destructors, since the GC wouldn't collect those references until everything that points to them is destroyed.Are you saying that a proper class destructor can't be written without modifying the language? Thanks, Bradley [2] http://www.digitalmars.com/d/attribute.html#scope
Jan 25 2007
Bradley Smith wrote:Jarrett Billingsley wrote:No, that paragraph was about a suggestion that it *should* be :).I remember someone suggesting that 'scope' be a valid modifier for class instance variables, and it'd basically mean "when this class gets destroyed, destroy this other instance as well." Like auto-deletion when you use a scope reference in a function:Is scope a valid modifier for a data member?I think he's saying that it can be fixed by modifying the GC (which isn't so much part of the language as it is of the standard library).Another solution would be to change the behavior of the GC so that deletion on program end _is_ deterministic. That is, it'd basically run a collection sweep, call finalizers on objects which don't have references to them, and keep doing that until nothing is left. That way, references to other classes would always be valid in destructors, since the GC wouldn't collect those references until everything that points to them is destroyed.Are you saying that a proper class destructor can't be written without modifying the language?
Jan 25 2007
Bradley Smith wrote:...Are you saying that a proper class destructor can't be written without modifying the language? Thanks, Bradley [2] http://www.digitalmars.com/d/attribute.html#scopeSome cases like closing a socket or a file opened with the unix open(2) are not affected, because the file is identified with an integer, which is stored in your class -- you can safely close it. But, even if the object is a heap object, there exists a fairly simple way to do this *without* modifying the GC algorithms. You can delay the destruction until the next GC cycle using a global table -- in the example below, the Foo object is never deleted until it is removed from the global table, which is done from the destructor, *after* the cleanup is done. Notes: 1. Don't do this for a linked list's next pointer or similar, or you will only remove one linked list element per GC run. 2. Look out for cycles -- this is essentially a reference counting technique, so cyclical data structures will never be claimed. 3. Don't reorder the lines marked A and B, or use a 'delete f' in the destructor because those actions are not safe if the GC runs while your destructor is running -- this could happen if this object is manually deleted or declared with scope, etc. class Foo { // must be called cleanup(); } class Bar { static bool[Foo] pity_the_foo; Foo f; this() { f = new Foo; pity_the_foo[f] = true; } ~this() { f.cleanup(); // A pity_the_foo.remove(f); // B // delete f; -- Don't do this } } Kevin
Jan 28 2007
Just an addendum to my previous reply - the technique I mention can also be used to implement 'weak pointers'. Kevin
Jan 28 2007
"Bradley Smith" <digitalmars-com baysmith.com> wrote in messageJarrett Billingsley wrote:How is a class supposed to release something for which it no longer has a valid reference?I remember someone suggesting that 'scope' be a valid modifier for class instance variables, and it'd basically mean "when this class gets destroyed, destroy this other instance as well." Like auto-deletion when you use a scope reference in a function: class ResourceHolder { scope SomeResource mRsrc; this(char[] name) { mRsrc = new SomeResource(name); } } .. { scope holder = new ResourceHolder("a.file"); ... } // holder is destroyed here, and so is its mRsrc member. Another solution would be to change the behavior of the GC so that deletion on program end _is_ deterministic. That is, it'd basically run a collection sweep, call finalizers on objects which don't have references to them, and keep doing that until nothing is left. That way, references to other classes would always be valid in destructors, since the GC wouldn't collect those references until everything that points to them is destroyed.Hmm, I think I've run into this problem just a few days ago, as my own (very basic) LinkedList implementation was getting a little bit heavy on the GC. So, I thought I might be able to make it a little bit quicker by adding a destructor and deleting the Nodes that point to the actual data (the Nodes that the LinkedList has created). But suddenly I wasn't able to iterate through the Nodes while in the destructor, and so, I wasn't able to delete them. I'm not really sure if the GC is causing the one second pauses that I get when I'm on a really heavy load doing thousands of LinkedLists and releasing them. Maybe I should try using pure D dynamic arrays instead of my own container... Or try Tango when it's released. Do the dynamic arrays in D, or the Tango containers use GC? And about the scope keyword on a class member suggestion: What about the "auto" keyword. What's the difference between the auto and the scope keywords? class Any { auto SomeOther m_someOther; this() { m_someOther = new SomeOther(); } ~this() { //automatically deletes m_someOther... } }
Jan 26 2007
Jonas Kivi wrote:And about the scope keyword on a class member suggestion: What about the "auto" keyword. What's the difference between the auto and the scope keywords?"scope" is for automatic deletion. "auto" is for type inference. "auto" used to also be for automatic deletion, but its dual purpose was annoying, especially when you wanted to have both of its meanings apply (which wasn't possible). "auto" may still do automatic deletion when a type is also supplied, I'm not sure, but if so that's just for backwards compatibility. Don't use it for that in new code.
Jan 26 2007
"Frits van Bommel" <fvbommel REMwOVExCAPSs.nl> wrote in message news:epcrvr$hen$1 digitaldaemon.com..."auto" is for type inference.No ;) 'auto' is the default (hidden) storage class for local variables in a function. So the following declarations are equivalent: int x; auto int x; 'auto' is in the same family as 'static', 'const', and 'scope'. 'auto' does not do type inference. Type inference is triggered when there is a storage class, but no type. So these all trigger type inference: auto x = 5; static y = 10; const z = 15; scope f = new Foo(); 'auto' just happens to be the most common of the bunch, and so you see it a lot more. But it doesn't mean "infer the type.""auto" may still do automatic deletion when a type is also supplied, I'm not sure, but if so that's just for backwards compatibility. Don't use it for that in new code.Nope.
Jan 26 2007
Jarrett Billingsley wrote:"Frits van Bommel" <fvbommel REMwOVExCAPSs.nl> wrote in message news:epcrvr$hen$1 digitaldaemon.com...Right, forgot about all that for a moment[1]. However, that is how it *should* be. And if you follow those rules, it works just fine, so... [1] Which is weird, since the code I'm currently working on uses 'const' for type inference wherever possible ;)"auto" is for type inference.No ;) 'auto' is the default (hidden) storage class for local variables in a function. So the following declarations are equivalent: int x; auto int x; 'auto' is in the same family as 'static', 'const', and 'scope'. 'auto' does not do type inference. Type inference is triggered when there is a storage class, but no type. So these all trigger type inference: auto x = 5; static y = 10; const z = 15; scope f = new Foo(); 'auto' just happens to be the most common of the bunch, and so you see it a lot more. But it doesn't mean "infer the type."
Jan 26 2007
Frits van Bommel kirjoitti:Jonas Kivi wrote:Ahh, thanks for clearing that up. I changed all the auto-keywords in my own projects code to scope. There were some 50 of them. I'm not sure. It looked like it had some effect on my program, so maybe the auto keyword doesn't even work for it's old purpose anymore? Don't know. But thanks, now I only have my destructors unfunctional.And about the scope keyword on a class member suggestion: What about the "auto" keyword. What's the difference between the auto and the scope keywords?"scope" is for automatic deletion. "auto" is for type inference. "auto" used to also be for automatic deletion, but its dual purpose was annoying, especially when you wanted to have both of its meanings apply (which wasn't possible). "auto" may still do automatic deletion when a type is also supplied, I'm not sure, but if so that's just for backwards compatibility. Don't use it for that in new code.
Jan 26 2007
Jonas Kivi wrote:Frits van Bommel kirjoitti:Well, one way to make sure a class never gets GC'ed is to make it a 'scope class'. Then you can only keep references as scope variables, and they always get explicitly deleted. The only problem is that you're then not allowed to keep them in member variables, just function-local vars.Jonas Kivi wrote:Ahh, thanks for clearing that up. I changed all the auto-keywords in my own projects code to scope. There were some 50 of them. I'm not sure. It looked like it had some effect on my program, so maybe the auto keyword doesn't even work for it's old purpose anymore? Don't know. But thanks, now I only have my destructors unfunctional.And about the scope keyword on a class member suggestion: What about the "auto" keyword. What's the difference between the auto and the scope keywords?"scope" is for automatic deletion. "auto" is for type inference. "auto" used to also be for automatic deletion, but its dual purpose was annoying, especially when you wanted to have both of its meanings apply (which wasn't possible). "auto" may still do automatic deletion when a type is also supplied, I'm not sure, but if so that's just for backwards compatibility. Don't use it for that in new code.
Jan 26 2007