mardi 7 novembre 2023

Calling the std::future destructor when an exception is thrown

There is this code:

 #include <chrono>
 #include <future>
 #include <iostream>

 using namespace std::chrono_literals;

 int main()
 {
     try {
         std::atomic<bool> stopTask;
         stopTask.store(false, std::memory_order_seq_cst);

         auto future = std::async([&stopTask]() {
             for (int i = 0; i < 20; ++i)
             {
                 if (stopTask.load(std::memory_order_seq_cst))
                     break;
                 std::this_thread::sleep_for(500ms); // Imitation of useful task.
             }
         });

         // Some useful work in the main thread.
         throw std::runtime_error("Error"); // Oops! Something went wrong in the main thread.

         // Normal shutdown.
         stopTask.store(true, std::memory_order_seq_cst);
         future.get();
     }
     catch (...)
     {
         std::cout << "Exception caught" << std::endl;
     }
 }

I run a long-running task in a separate thread using std::async and receive std::future on it. And after that, an exception is thrown in the main thread. The stack unwinding begins and the destructors are called. As soon as it reaches the std::future destructor, stack unwinding stops and the main thread blocks until the second thread finishes.

It looks like that something is wrong. I have seen recommendations to make destructors as fast as possible and not to perform long operations in them. But here the destructor is very slow and stack unwinding takes a very long time.

Question: is it correct that stack unwinding takes so long? Maybe I'm doing something wrong and actually need to do something differently? What are the best practices in such cases?


In this particular code, the std::future destructor can be speeded up by making a wrapper class around std::atomic stopTask like RAII, which will set stopTask to true in the destructor. But it can still take up to 500 ms to execute the destructor. And this can no longer be speeded up, since in my application the real minimal operation takes so much time.

Aucun commentaire:

Enregistrer un commentaire