2016-05-31 5 views
3

Можно ли создать 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 Wether или не get(), в конце концов называется на std::future, но так как я не мог найти что-нибудь в C++ документы о этот шаблон использования, я бы хотел убедиться, что он официально поддерживается.

ответ

0

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

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

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

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

+0

Я действительно заметил поведение блокировки с помощью 'std :: async', поэтому я перешел на' std :: packaged_task'. Я не уверен, что вы подразумеваете под «правильностью вашего кода, становится сомнительным»? До тех пор, пока '~ Result()' гарантированно будет вызван каким-либо образом общим состоянием, то что может пойти не так? – Pol

+0

Действительно, вы правы, если класс Result предназначен для хранения памяти. Но редко бывает, что вам придется хранить не владеющие данными. В таких случаях забыть о вызове 'get_future' было бы неверно. Если это сделано с целями (как в вашем примере), то, вероятно, хорошо, если ресурс позаботился об RAII. – Arunmu