On Sun, Aug 25, 2013 at 12:18:27AM +0200, Tobias Pankrath wrote: > On Saturday, 24 August 2013 at 20:11:14 UTC, H. S. Teoh wrote: > >How would you use RAII to solve this problem? If I have a class: > > > > class C { > > Resource1 res1; > > Resource2 res2; > > Resource3 res3; > > this() { > > ... > > } > > } > > > >How would you write the ctor with RAII such that if it successfully > >inits res1 and res2, but throws before it inits res3, then only res1 > >and res2 will be cleaned up? > > Like someone else already proposed: Using a wrapper type W that > releases the resources in it's destructor. W.init wouldn't release > anything. So by definition (if I recall the rules correctly) every > new instance of C would have res3 = Resource3.init prior to it's > constructor called. > > Now make sure that a) res3's destructor gets called (check) b) > res3's destructor may be called on Resource3.init. That would be a > new rule similar to 'no internal aliasing' and c) that every > constructor of C either sets res3 to a destructable value or does > not touch it at all ('transactional programming'). [...]
But don't you still need to manually cleanup in the case of ctor failure? AFAIK, the dtor is not invoked on the partially-constructed object if the ctor throws. So you'd still have to use scope(failure) to manually release the resource. To prove my point, here is some sample code that (tries to) use RAII to cleanup: import std.stdio; struct Resource { int x = 0; this(int id) { x = id; writefln("Acquired resource %d", x); } ~this() { if (x == 0) writefln("Empty resource, no cleanup"); else writefln("Cleanup resource %d", x); } } struct S { Resource res1; Resource res2; Resource res3; this(int) { res1 = Resource(1); res2 = Resource(2); assert(res1.x == 1); assert(res2.x == 2); throw new Exception("ctor failed!"); res3 = Resource(3); // not reached assert(res3.x == 3); // not reached } } void main() { try { auto s = S(123); } catch(Exception e) { writeln(e.msg); } } Here is the program output: Acquired resource 1 Empty resource, no cleanup Acquired resource 2 Empty resource, no cleanup ctor failed! As you can see, the two resources acquired in the partially-constructed object did NOT get cleaned up. So, RAII doesn't work in this case. The two interspersed cleanups were presumably cause by Resource.init being destructed when res1 and res2 were assigned to. But after being assigned to, res1 and res2's dtors were NOT invoked. So I think my scope(this) idea has some merit, since it will correctly handle this case. :) T -- Many open minds should be closed for repairs. -- K5 user