According to the cppreference.com the std::call_once should work correctly with functions which might throw an exception. Having said that, testing the example represented there it results in an infinite waiting instead of joining all threads.
the example from the page above:
#include <iostream>
#include <thread>
#include <mutex>
std::once_flag flag1, flag2;
void simple_do_once()
{
std::call_once(flag1, [](){ std::cout << "Simple example: called once\n"; });
}
void may_throw_function(bool do_throw)
{
if (do_throw) {
std::cout << "throw: call_once will retry\n"; // this may appear more than once
throw std::exception();
}
std::cout << "Didn't throw, call_once will not attempt again\n"; // guaranteed once
}
void do_once(bool do_throw)
{
try {
std::call_once(flag2, may_throw_function, do_throw);
}
catch (...) {
}
}
int main()
{
std::thread st1(simple_do_once);
std::thread st2(simple_do_once);
std::thread st3(simple_do_once);
std::thread st4(simple_do_once);
st1.join();
st2.join();
st3.join();
st4.join();
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();
}
In my case it results in the infinite waiting after the following output:
Simple example: called once
throw: call_once will retry
for all the following versions the result is the same.
clang++
clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
g++
g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
g++-10 (Ubuntu 10.2.0-5ubuntu1~20.04) 10.2.0
What does that mean?