std::call_once
的标准示例 cppreference.com以这种方式描述异常调用的行为,据我了解,其他线程等待第一个进入 std::call_once
并且在发生异常的情况下,下一个线程将尝试执行 std::call_once
。虽然在线编译器确认了这种行为,但我无法在本地重现它。对于最小的例子
#include <iostream>
#include <thread>
#include <mutex>
std::once_flag flag;
void may_throw_function(bool do_throw)
{
if (do_throw) {
std::cout << "throw: call_once will retry\n";
throw std::exception();
}
std::cout << "Didn't throw, call_once will not attempt again\n";
}
void do_once(bool do_throw)
{
try {
std::call_once(flag, may_throw_function, do_throw);
}
catch (...) {}
}
int main()
{
std::thread t1(do_once, true);
std::thread t2(do_once, true);
std::thread t3(do_once, false);
std::thread t4(do_once, true);
t1.join();
t2.join();
t3.join();
t4.join();
}
复制自cppreference.com执行在第一次抛出后卡住并永远运行
编译是用g++-5 -std=c++14 source.cpp -pthread
(version g++ (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
) 或 clang++-6.0 source.cpp -pthread
(version clang version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final)
) .
将更多输出放入代码显示,所有线程都已启动,但只有最先抛出的线程才会结束。所有其他人似乎都在 std::call_once
声明之前等待。因此我的问题是:是否保证通知正在等待第一个线程完成的线程?
最佳答案
Is the notification of threads that are waiting for the first thread to finish guaranteed?
不涉及通知,但如果我将您的问题解释为:
Is
t4.join()
guaranteed to return?
是的。
[thread.once.callonce]
template<class Callable, class... Args> void call_once(once_flag& flag, Callable&& func, Args&&... args);
Effects: An execution of
call_once
that does not call its func is a passive execution.
An execution ofcall_once
that calls its func is an active execution. An active execution shall callINVOKE(std::forward<Callable>(func), std::forward<Args>(args)...)
.
If such a call to func throws an exception the execution is exceptional, otherwise it is returning.
An exceptional execution shall propagate the exception to the caller ofcall_once
. Among all executions ofcall_once
for any givenonce_flag
: at most one shall be a returning execution; if there is a returning execution, it shall be the last active execution; and there are passive executions only if there is a returning execution.Synchronization: For any given once_flag: all active executions occur in a total order; completion of an active execution synchronizes with the start of the next one in this total order; and the returning execution synchronizes with the return from all passive executions.
A call_once
仅当另一个call_once
时才会执行返回(意思是:没有抛出)。由于观察到总顺序,因此可以保证:
-
t1
是主动异常执行还是被动执行; -
t2
是主动异常执行还是被动执行; -
t3
是主动返回执行; -
t4
是主动异常执行还是被动执行;
由于被动执行返回,t4
保证返回。
由 user cpplearner 报告, a bug of pthread_once
使问题中列出的程序挂起(demo)。
关于c++ - 异常调用后是否保证 std::call_once 的线程通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57390526/