digitalmars.D - RAII support
- Tristam MacDonald (5/5) Jul 11 2007 Now that the whole const issue seems to have died down, I wanted to get ...
- downs (38/39) Jul 11 2007 So it's hacks you want? :D
Now that the whole const issue seems to have died down, I wanted to get a few thoughts on what people are using to work arround the missing RAII support. So an overview of what I *think* is the current situation, please correct me if I am wrong: Basically, the only tool for RAII is 'scope' reference/classes. They are very handy for locks (mutexs, etc.) but they are not so useful for general resource management, since they cannot be returned from functions, or stored somewhere. The *only* use of destructors on normal (i.e. non-scope) is to free malloced memory - While the program is running. Non-malloced memory is GC'd anyway, and you can't use the destructor to free other resources, because it is not guarenteed to ever be called (and often isn't called when the program exits). So the only method for managing shared memory, file handles, etc. is to perform explicit reference counting (i.e. AddRef()/DeRef()), just like in plain old C. If this were C++, we could wrap the AddRef()/DeRef() calls in a handle struct, which would automate the reference counting, but unfortunately, D still doesn't have constructors/destructors/assignment for structs (i.e. value types), so we are stuck with C-style manual ref counting. And that about covers it... Is anything planned (in the *near* future) to fix this? And does anyone have hacks/gimmicks for working around this (other than not having shared resources)?
Jul 11 2007
Tristam MacDonald wrote:[...] does anyone have hacks/gimmicks for working around this (other than not having shared resources)?So it's hacks you want? :D Here's one that exploits the GC to do basic reference "counting" (referred/not referred). Remember, relying on the GC is generally a bad thing :D (Code originally written for D.learn) import std.stdio, std.gc; typedef size_t hidden; // pointer that is hidden from the GC hidden hide(Object ptr) { return cast(hidden)(~(cast(size_t)cast(void*)ptr)); } Object show(hidden h) { return cast(Object)~h; } class refcounter { hidden ptr; this() { ptr=hide(new class(this) { refcounter rc; this(refcounter r) { rc=r; } ~this() { writefln("Destructor called, telling refcounter to clean up"); rc.cleanUp; } }); } Object issueReference() { return new class(show(ptr)) { Object reftest; this(Object obj) { reftest=obj; writefln("Reference counted object constructed"); } ~this() { writefln("Reference counted object destroyed"); } }; } void cleanUp() { writefln("CleanUp called. No references left. Clean up resource."); } } void main() { auto r=new refcounter; auto a=r.issueReference(); auto b=r.issueReference; writefln("When calling fullCollect here, nothing will happen."); std.gc.fullCollect; writefln("Now delete the objects."); delete a; delete b; writefln("Again, fullCollect. But this time: "); std.gc.fullCollect; writefln("Exiting"); } Have fun! :D
Jul 11 2007