I have a question similar to How to manage object life time using Boost library smart pointers? but, in my case, the "object" isn't a C++ object at all, but an opaque type returned/passed out from a C API. The type does not have pointer semantics, i.e., there is no dereferencing; it is, however, passed as an argument to other functions in the C API. The type also has a definitive close
API which must be called in order to clean up internal resources.
So, I have a C API that's something along the lines of
opaque_legacy_type_t x;
XXopen(..., &x); // allocates/opens resource and fills out 'x' to be used later
XXdoSomethingWithResource(x, ...); // do something with resources related to 'x'
...more actions...
XXclose(x); // closes and cleans up resources related to 'x'
For various reasons, in my C++ code I would like to manage "instances" of opaque_legacy_type_t much like I would manage heap-allocated object instances, i.e. with similar sharing semantics as boost::shared_ptr<>
. It seems that shared_ptr
offers enough that I can manage calling XXclose
by doing this:
opaque_legacy_type_t x;
XXopen(..., &x);
boost::shared_ptr<opaque_legacy_type_t> managed(x, XXclose);
But, since opaque_legacy_type_t
doesn't have pointer semantics, the usage of managed
is a bit clumsy.
What I'd like to do is have something like a managed_type
that is similar to shared_ptr
, and am looking for ideas that don't require me to write it all.
EDIT: I corrected my original screw-up in the example. The legacy API takes the opaque type by value rather than by pointer.
You could use boost smart pointers together with the pimpl idom:
class shared_opaque_legacy_type_t {
struct impl {
opaque_legacy_type_t t;
impl(...) { XXOpen(..., t); }
~impl(...) { XXClose(t); }
}
boost::shared_ptr<impl> _impl;
public:
shared_opaque_lagacy_type_t(...) : _impl(new impl(...)) {}
opaque_legacy_type_t* get() {
return _impl->t;
}
};
shared_opaque_legacy_type_t x(...);
XXdoSomethingWithResource(x.get(), ...);
The drawback is that you could still call XXclose(x.get())
and invalidate your object.
UPDATE: Fixed it. :-)