According to RAII when I destroy the object, its resources are deallocated. But what if the destruction of the object requires asynchronous operations?
Without using RAII I can call close
method of my class that will call necessary async operations and will keep shared_ptr
to my object (using shared_from_this
) in order to gracefully process callbacks from the async operations. After calling close
I can remove my pointer to the object since I do not need it anymore - but I know that the object will not be removed until the async operations are executed.
But how can I achieve this using RAII? One of the possible solutions can be using a wrapper that when destructed will call close
method of by object. But.. will it mean that my classes are RAII classes?
class Resource: public std::enable_shared_from_this<Resource> {
int id;
public:
close() {
some_async_functin([t = shared_from_this()] {
std::cout << "Now I am closed " << t->id << std::endl;
}
}
}
My solution:
class ResourceWrapper {
std::shared_ptr<Resource> res;
~ResourceWrapper() {
res.close();
}
}
An object o to be asynchronously destroyed with respect to the thread, T, in which it was created cannot itself be managed via RAII, because destruction of stack-allocated objects is inherently synchronous. If o is managed via the RAII model then thread T will execute its destructor when the innermost block containing its declaration terminates, until the destructor terminates.
If you do not want to occupy T with releasing o's resources (yet ensure that they are in fact released), then you must delegate the resource release to another thread. You can do that either
directly, by creating o dynamically with new
and dispatching the corresponding free
asynchronously (e.g. via std::async
), or
indirectly with RAII, by having o's destructor dispatch the resource cleanup for separate asynchronous release (again, via std::async
or similar).
The latter is indirect because it requires a separate object or objects to represent the resource(s) being cleaned up until the cleanup is complete -- especially so if there are callbacks involved or similar. You face the same issue with these objects that you do with o itself. There is nothing inherently wrong with this indirection, by the way. RAII still provides the benefits it usually does.