C++中的异步销毁和RAII

Asynchronous Destruction and RAII in C++

本文关键字:RAII 异步 C++      更新时间:2024-09-29

根据RAII,当我销毁对象时,它的资源将被释放。但是,如果对象的销毁需要异步操作,该怎么办?在不使用RAII的情况下,我可以调用类的close方法,该方法将调用必要的异步操作,并将shared_ptr保留到我的对象(使用shared_from_this(,以便优雅地处理来自异步操作的回调。在调用close之后,我可以删除指向该对象的指针,因为我不再需要它了——但我知道,在执行异步操作之前,该对象不会被删除。

但是如何使用RAII实现这一点呢?一种可能的解决方案是使用一个包装器,该包装器在被销毁时将调用by对象的close方法。但是这是否意味着我的课程是RAII课程?

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;
}
}

}

我的解决方案:

class ResourceWrapper {
std::shared_ptr<Resource> res;
~ResourceWrapper() {
res.close();
}
}

要相对于线程异步销毁的对象o(创建该对象的线程T(本身不能通过RAII进行管理,因为堆栈分配对象的销毁本质上是同步的。如果o是通过RAII模型管理的,那么当包含其声明的最内部块终止时,线程T将执行其析构函数,直到析构函数终止。

如果您不想占用T来释放o的资源(但要确保它们确实已释放(,则必须将资源释放委托给另一个线程。你可以通过

通过使用new动态创建o并异步调度相应的free(例如通过std::async(或
  • 通过让o的析构函数调度资源清理以进行单独的异步发布(同样,通过std::async或类似方式(,间接地使用RAII。

  • 后者是间接的,因为它需要一个或多个单独的对象来表示正在清理的资源,直到清理完成——尤其是在涉及回调或类似的情况下。这些对象与o本身所面临的问题相同。顺便说一句,这种间接性本身并没有什么错。RAII仍然提供它通常提供的好处。

    您需要两个类:AcquirableResourceAcquiredResource。您首先创建AcquirableResource实例,该实例在关闭后仍然有效(甚至可能用于重新打开(;那么AcquirableResource中的AcquiredResource就是打开的资源。这完全是RAII。

    // define the AcquirableResource and AcquiredResource
    int main() {
    AcquirableResource ares("filename.txt");
    // ... your code here ...
    {
    auto res(ares); // open
    if (!res) { /* error handler */ }
    // ... your code here ...
    // res goes out of scope, signals ares
    // ares closes file (can be async)
    }
    // ares is still valid here
    // ... your code here ...
    // ares goes out of scope, dtor close in sync
    }