Forum Navigation
No single safe way to notify other objects of my termination from both GC and delete
Posted: 04/24/10 15:27:05I'm having problems maintaining proper safe resource-management in D1/Tango. My basic scenario is that my application holds an asset open through a Socket to upstream nodes, while forwarding it to downstream nodes. Whenever downstream nodes release the Asset, it should also be released upstream.
My problem is finding a safe way to do this, that does not rely on forced explicit termination from downstream nodes. Essentially, I can't use the dtor, since I can't call any members on the upstream socket (it may have been GC:ed). I could use dispose, but that won't get called by explicit delete. I could write a complex harness using a combo of rt_attachDisposeEvent, but AFAIU that has the basic problems of dispose, it's not called on explicit delete. Could perhaps be worked around by keeping a list of remote references, which is purged by rt_attachDisposeEvent, and cleansed by the dtor, but it seems like something like this should be made easier than that by the runtime/stdlib.
Here:s a small diagram showing the problem. http://imgpaste.com/i/llmkp.png. In short; there is no single runtime-supported way to notify other objects of my termination from both GC and delete.
One ?simple? solution would be to ensure that dispose/rt_attachDisposeEvent gets called also for explicit delete, in which case dispose would be a good point to cleanup resources (in which case one may question the purpose of the dtor?).
Another could perhaps be to make the GC work in multiple passes, one collection-pass, one finalization, and one destruction, where the dtor is called during finalization, ensuring calling methods on other objects is safe in the dtor. (Eliminating the need for dispose, I think?)
Yet a third option could perhaps be to implement some kind of RefCounting? base-class in Tango, with smart-pointers for other objects to reference it. D1 is missing a few overloadable operators for fully mimicking pointers, but it could work with some compromises. The advantage would be more predictable timing for when resources are released, the drawback would be performance-hits for referencing those objects, and those objects can not inherit any other base-class, imposing design-limitations, a third drawback is of course that the programmer must actively remember when to access through smart-pointer instead of direct reference. (Also, can class-allocators be overridden in child-classes?)
Personally, without much understanding of the entire complexity of a garbage collector, I'd think that option 2 AND 3 should both be implemented, making the dtor in general more usable (as of now, I really don't see ANY other sensible use for it than closing C-API-resources, or explicit non-GC-allocated objects). Then additionally, a ref-counting structure would be useful for deterministic destruction in some scenarios. (Also, I think it should be much easier to implement if the dtor is deterministicly safe.)
Thoughts?