www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - RAII support

reply Tristam MacDonald <swiftcoder gmail.com> writes:
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
parent downs <default_357-line yahoo.de> writes:
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