Безопасно ли никогда не получать результат std::future из std::packaged_task?

Безопасно ли создавать std::future из std::packaged_task, который выполняется в отдельном потоке, но не всегда получает его результат?

#include <future>
#include <thread>

class Result {
  Result() {}
  ~Result() {}
};

void foo() {
  std::packaged_task<Result()> task(..);
  auto future = task.get_future();
  std::thread thread(std::move(task), ...);
  thread.detach();
  if (future.wait_for(std::chrono::milliseconds(timeout_ms)) == std::future_status::ready) {
    auto result = future.get();  <--- Task didn't take too long, retrieve future result
    ...
  }
}  <--- Task is taking too long, just abort and never call future.get()

Кажется, работает на Clang / libC++: ~Result() вызывается по возвращаемому результату std::packaged_task мокрая или нет get() в конечном итоге призван на std::future, но поскольку я не смог найти в документации по C++ ничего об этом шаблоне использования, я хотел бы убедиться, что он официально поддерживается.

1 ответ

Решение

Это зависит от того, что вы считаете безопасным для вашей программы.
Для контекста, который вы показали, это безопасно, как в:

  • Это не блокирует, когда future уничтожается, прежде чем делать get в теме. Если будущее было создано с использованием std::async а если не позвонишь get на нем, прежде чем он будет уничтожен, он будет заблокирован, пока не станет доступен результат.
    Узнайте больше об этом здесь: http://en.cppreference.com/w/cpp/thread/future/~future

эти действия не будут блокировать совместное состояние для готовности, за исключением того, что оно может блокироваться, если выполняются все следующие условия: общее состояние было создано с помощью вызова std::async, общее состояние еще не готово, и это была последняя ссылка на общее состояние.

Теперь, что если Result класс держал не владеющую памятью (по какой-либо причине) или какой-либо другой ресурс, который должен быть освобожден вручную. В этом случае правильность вашего кода становится сомнительной. Лучше всего было бы отправить его в какой-нибудь фоновый поток для медленных задач.

Другие вопросы по тегам