Copying and assigning of resource-owning objects

M

Marijn

Say i have an object that represents or holds a resource like an open
file, a block of memory on the heap, or an openGL texture object. The
constructor acquires the resource, and the destructor releases it. I
want to implement efficient copying and assignment for this object -
the copy constructor passes on the 'handle' (file pointer, memory
pointer, or opengl texture id) to the new object, and invalidates the
old object. I guess this is how the std::auto_ptr works too. I can
come up with several ways to do this, but i'd like to see how it
usually done, since i guess this is a quite common problem and people
will undoubtedly have come up with a brilliant solution.
Possible method: Have a boolean valid flag in the object, all methods
that require the resource check this flag and report error when the
object is not valid. Destructor only releases the resource if the
object is valid. The copy constructor and assignment operator set this
flag to false in the original object and copy the handle variable
instead of initalizing their own resource. Is this The Way To Do It,
or does it have flaws?

Marijn Haverbeke
 
V

Victor Bazarov

Marijn said:
Say i have an object that represents or holds a resource like an open
file, a block of memory on the heap, or an openGL texture object. The
constructor acquires the resource, and the destructor releases it. I
want to implement efficient copying and assignment for this object -
the copy constructor passes on the 'handle' (file pointer, memory
pointer, or opengl texture id) to the new object, and invalidates the
old object. I guess this is how the std::auto_ptr works too. I can
come up with several ways to do this, but i'd like to see how it
usually done, since i guess this is a quite common problem and people
will undoubtedly have come up with a brilliant solution.
Possible method: Have a boolean valid flag in the object, all methods
that require the resource check this flag and report error when the
object is not valid. Destructor only releases the resource if the
object is valid. The copy constructor and assignment operator set this
flag to false in the original object and copy the handle variable
instead of initalizing their own resource. Is this The Way To Do It,
or does it have flaws?

The matter gets a bit more complicated when you consider the need to
have temporaries of that type or const objects of that type. You
probably need to implement some kind of reference counting scheme
for that. It's not that difficult, but it's relatively tedious (to
cover all bases, mainly).

You probably don't need a boolean flag. Keep your resources pointers
and simply set them to 0 when the resource is freed or transferred to
another object. Implement the copy constructor using a non-const
reference and let the constructed object transfer the ownership from
the object from which it's being constructed:

class MyType {
...
MyType(MyType& from) : myresource(from.myresource) {
from.resourceIsTakenBy(this);
}
void resourceIsTakenBy(MyType* heir) {
myresource = 0; // any other processing? Logging?
}
};

Take a look at the implementation of different smart pointers (the
auto_ptr in your standard library, the Boost's one, whatever else
you can find on the web). Just as you've guesses, they do have all
those features: ownership and its transfer, cleaning up when dying,
some have reference counting...

Victor
 
M

Marijn

Thanks for the reply!

Victor Bazarov said:
The matter gets a bit more complicated when you consider the need to
have temporaries of that type or const objects of that type. You
probably need to implement some kind of reference counting scheme
for that. It's not that difficult, but it's relatively tedious (to
cover all bases, mainly).

I can see the problem with const objects, but what issues can come up with
temporaries? (in the problem that led to this post i do not need consts, just
temporary objects - pushing stuff into std containers right away, as in
container.push_back(TextureObject(45)); )
I used the reference counting thing to implement a string class (yeah i know,
i like reinventing wheels), but i was aiming for a simpler, more efficient, less
error-prone approach here. I do not need multiple objects pointing at the same
resource, so i'll just cop out and use an invalidation scheme.
You probably don't need a boolean flag. Keep your resources pointers
and simply set them to 0 when the resource is freed or transferred to
another object.

Sure. I was talking about generic resource, some of which might have identi-
fiers that could be zero, but for pointer NULL works okay.
Take a look at the implementation of different smart pointers (the
auto_ptr in your standard library, the Boost's one, whatever else
you can find on the web). Just as you've guesses, they do have all
those features: ownership and its transfer, cleaning up when dying,
some have reference counting...

Good idea, i was already imitating the std::auto_ptr behaviour, but why
imitate when you can literally copy how it is done there, ha.

Marijn
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top