[英]Is notification of threads guaranteed for std::call_once after exceptional call
The standard example for std::call_once
on cppreference.com describes the behavior for exceptional calls that way, that to my understanding other threads wait for the first entering the std::call_once
and in case of an exception the next thread will try to execute the std::call_once
. cppreference.com上std::call_once
的标准示例描述了异常调用的行为,这是我理解的其他线程等待第一次进入std::call_once
,如果是异常,下一个线程将尝试执行std::call_once
。 While online compilers confirm this behavior, I cannot reproduce it locally. 虽然在线编译器确认了这种行为,但我无法在本地重现它。 For the minimal example 对于最小的例子
#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();
}
copied from cppreference.com the execution is stuck after the first throw and runs forever 从cppreference.com复制后,执行在第一次投掷后被卡住并永远运行
Compilation is done with g++-5 -std=c++14 source.cpp -pthread
(version g++ (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
) or clang++-6.0 source.cpp -pthread
(version clang version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final)
). 编译使用g++-5 -std=c++14 source.cpp -pthread
(版本g++ (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
)或clang++-6.0 source.cpp -pthread
(版本) clang version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final)
)。
Putting more output into the code shows, that all threads are started, but only the threads that throws first ever ends. 将更多输出放入代码中会显示所有线程都已启动,但只有先抛出的线程才会结束。 All others seems to wait before the std::call_once
statement. 所有其他人似乎都在std::call_once
语句之前等待。 Hence my question: Is the notification of threads that are waiting for the first thread to finish guaranteed? 因此我的问题是:等待第一个线程的线程通知是否有保证?
Is the notification of threads that are waiting for the first thread to finish guaranteed? 是否等待第一个线程完成保证的线程通知?
There is no notification involved, but if I interpret your question as: 没有涉及通知,但如果我将您的问题解释为:
Is
t4.join()
guaranteed to return?t4.join()
保证返回吗?
Yes it is. 是的。
[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. 效果 :不调用其func的call_once
的执行是被动执行。
An execution ofcall_once
that calls its func is an active execution. 调用其func的call_once
的执行是一个活动执行。 An active execution shall callINVOKE(std::forward<Callable>(func), std::forward<Args>(args)...)
. 活动执行应调用INVOKE(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. 如果对func的这种调用抛出异常,则执行异常,否则返回。
An exceptional execution shall propagate the exception to the caller ofcall_once
. 异常执行应将异常传播给call_once
的调用者。 Among all executions ofcall_once
for any givenonce_flag
: at most one shall be a returning execution; 在任何给定的once_flag
的call_once
所有执行中:最多一个应该是返回执行; 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 ; 同步 :对于任何给定的once_flag: 所有活动执行都按总顺序发生 ; 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
will not be executed only if another call_once
returned (meaning: did not throw). 一个call_once
只有 1人将不被执行call_once
返回(:没扔的意思)。 And since total order is observed, it is guaranteed that: 由于遵守了总订单,因此可以保证:
t1
is an active exceptional execution or a passive execution; t1
是主动例外执行或被动执行; t2
is an active exceptional execution or a passive execution; t2
是主动例外执行或被动执行; t3
is an active returning execution; t3
是主动返回执行; t4
is an active exceptional execution or a passive execution; t4
是主动例外执行或被动执行; And since a passive execution returns, t4
is guaranteed to return. 并且由于被动执行返回,因此保证t4
返回。
Reported by user cpplearner , a bug of pthread_once
make the program listed in the question hang ( demo ). 用户cpplearner报告, pthread_once
的错误使问题中的程序挂起( 演示 )。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.