请考虑以下代码:
template <typename func_t, typename ... Args>
auto waiter (func_t func, const Args &... args) -> decltype(func(args...)) {
const static std::chrono::milliseconds max_time(10);
auto task = std::packaged_task<decltype(func(args...))()>(std::bind(func, args...));
auto handle = task.get_future();
std::thread th(std::move(task)); // here
if (handle.wait_for(max_time) == std::future_status::timeout) {
th.detach(); // and here
throw std::runtime_error("timeout");
} else { // and here
th.detach();
return handle.get();
}
}
我可以安全地从std::thread
获取内部std::future
并将其分离吗?我猜它是明显的UB。 waiter()
函数旨在获取任何可调用对象,调用它并在任何
是真的。我试图在很多方面做到这一点,但总有一个问题。我意识到问题是C ++ 14没有流程支持。 第一次尝试:
template <typename func_t, typename ... Args>
auto waiter (func_t func, const Args &... args) -> decltype(func(args...)) {
const static std::chrono::milliseconds max_time(10);
decltype(func(args...)) result;
std::mutex mtx;
std::unique_lock<std::mutex> lock(mtx);
std::condition_variable cv;
thread th([&] {
result = func(args...);
cv.notify_all();
});
auto waiting_result = cv.wait_for(lock, max_time);
th.detach();
if (waiting_result == std::cv_status::timeout) {
throw std::runtime_error("timeout");
}
return result;
}
这里的问题是在抛出异常后,std::thread
th
仍在使用被杀死的引用运行。第二次尝试:
template <typename func_t, typename ... Args>
auto waiter (func_t func, const Args &... args) -> decltype(func(args...)) {
const static std::chrono::milliseconds max_time(10);
auto handle = std::async(std::launch::async, func, args ...);
if (handle.wait_for(max_time) == std::future_status::timeout) {
throw std::runtime_error("timeout");
} else {
return handle.get();
}
}
此问题是(据我所知)std::async::~async()
在其内部线程上调用某种std::thread::join()
,主线程仍在等待std::async
。 http://melpon.org/wandbox/permlink/Cyd2hYJCQSIxETqL
傻一个。
答案 0 :(得分:1)
您可以像第一次尝试一样分离线程,但是,正如您所说,线程将继续分离,直到它自己完成。
第二次尝试的问题是std::future
返回的std::async
有点特殊,因为它的析构函数将block until the thread finishes execution(与常规std::future
的析构函数不同)
我担心在C ++中,如果不杀死所有线程,就不可能安全地终止单个线程。问题产生于在执行期间在任意点安全地展开堆栈的困难。如果让我们说,放卷应该在一个不合适的地方进行,如ctor或dtor,它会破坏对象存储持续时间的规则。
有关详细信息,请参阅this answer。