raii

Ellery Newcomer ellery-newcomer at utulsa.edu
Sun Feb 28 12:16:32 PST 2010


Hello

The impetus:

> I agree, except I more and more think that scope classes were a mistake. Structs with destructors are a much better solution, and wrapping a class inside a struct would give it RAII semantics.

The problem:

In designing a library (or rather touching up someone else's library), I 
have a class (interface?) Foo, and it has a method close (actually 
several methods). Almost invariably (although conceivably not always), 
usage involves manipulating Foo, and then remembering to call close. 
That last part is obnoxious.

One obtains a Foo from function foo.

What I'd like is for the result of foo to have RAII semantics by 
default, with the possibility of nixing it if the user actually cares.

I want to take the burden of remembering that stupid close off the user.

For example:

void bar(){
   auto a = foo();
   a.doStuff();
}

has an implicit call to close after doStuff.

The impetus suggests I can do this by wrapping Foo inside a struct, but 
I'm not so sure how well this would work out. Also note that close can 
fail in a number of ways relating to file io.

So I wrote up a simple prototype.

Thoughts?




import std.stdio;
class Foo{
     int k;
     this(int i){
	writefln("bin %d",k);
	k = i;
     }
     void doStuff(){
	writefln("do stuff %d",k);
     }
     void close(){
	writefln("close %d",k);
     }
}
struct RAII(T){
     T b;
     bool extracted = false;
     alias b this;
     this (T i){
	assert(i !is null);
	writeln("in");
	b = i;
     }
     ~this(){
	writeln("~this");
	if(!extracted) b.close();
     }
     T extract(){
	assert(!extracted);
	T t = b;
	b = null;
	extracted = true;
	return t;
     }
}
RAII!(Foo) foo(int i){
     return RAII!(Foo)(new Foo(i));
}
void main(){
     auto a = foo(1);
     auto b = foo(2).extract();
     a.doStuff();
     b.doStuff();
}




More information about the Digitalmars-d-learn mailing list