|
8 | 8 |
|
9 | 9 | #include <__assert>
|
10 | 10 | #include <__thread/id.h>
|
| 11 | +#include <__utility/exception_guard.h> |
11 | 12 | #include <limits>
|
12 | 13 | #include <mutex>
|
13 | 14 |
|
@@ -205,56 +206,40 @@ void __call_once(volatile once_flag::_State_type& flag, void* arg,
|
205 | 206 | void (*func)(void*))
|
206 | 207 | {
|
207 | 208 | #if defined(_LIBCPP_HAS_NO_THREADS)
|
208 |
| - if (flag == once_flag::_Unset) |
209 |
| - { |
210 |
| -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS |
211 |
| - try |
212 |
| - { |
213 |
| -#endif // _LIBCPP_HAS_NO_EXCEPTIONS |
214 |
| - flag = once_flag::_Pending; |
215 |
| - func(arg); |
216 |
| - flag = once_flag::_Complete; |
217 |
| -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS |
218 |
| - } |
219 |
| - catch (...) |
220 |
| - { |
221 |
| - flag = once_flag::_Unset; |
222 |
| - throw; |
223 |
| - } |
224 |
| -#endif // _LIBCPP_HAS_NO_EXCEPTIONS |
| 209 | + |
| 210 | + if (flag == once_flag::_Unset) { |
| 211 | + auto guard = std::__make_exception_guard([&flag] { flag = once_flag::_Unset; }); |
| 212 | + flag = once_flag::_Pending; |
| 213 | + func(arg); |
| 214 | + flag = once_flag::_Complete; |
| 215 | + guard.__complete(); |
225 | 216 | }
|
| 217 | + |
226 | 218 | #else // !_LIBCPP_HAS_NO_THREADS
|
| 219 | + |
227 | 220 | __libcpp_mutex_lock(&mut);
|
228 | 221 | while (flag == once_flag::_Pending)
|
229 | 222 | __libcpp_condvar_wait(&cv, &mut);
|
230 |
| - if (flag == once_flag::_Unset) |
231 |
| - { |
232 |
| -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS |
233 |
| - try |
234 |
| - { |
235 |
| -#endif // _LIBCPP_HAS_NO_EXCEPTIONS |
236 |
| - __libcpp_relaxed_store(&flag, once_flag::_Pending); |
237 |
| - __libcpp_mutex_unlock(&mut); |
238 |
| - func(arg); |
239 |
| - __libcpp_mutex_lock(&mut); |
240 |
| - __libcpp_atomic_store(&flag, once_flag::_Complete, |
241 |
| - _AO_Release); |
242 |
| - __libcpp_mutex_unlock(&mut); |
243 |
| - __libcpp_condvar_broadcast(&cv); |
244 |
| -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS |
245 |
| - } |
246 |
| - catch (...) |
247 |
| - { |
| 223 | + if (flag == once_flag::_Unset) { |
| 224 | + auto guard = std::__make_exception_guard([&flag] { |
248 | 225 | __libcpp_mutex_lock(&mut);
|
249 | 226 | __libcpp_relaxed_store(&flag, once_flag::_Unset);
|
250 | 227 | __libcpp_mutex_unlock(&mut);
|
251 | 228 | __libcpp_condvar_broadcast(&cv);
|
252 |
| - throw; |
253 |
| - } |
254 |
| -#endif // _LIBCPP_HAS_NO_EXCEPTIONS |
255 |
| - } |
256 |
| - else |
| 229 | + }); |
| 230 | + |
| 231 | + __libcpp_relaxed_store(&flag, once_flag::_Pending); |
| 232 | + __libcpp_mutex_unlock(&mut); |
| 233 | + func(arg); |
| 234 | + __libcpp_mutex_lock(&mut); |
| 235 | + __libcpp_atomic_store(&flag, once_flag::_Complete, _AO_Release); |
257 | 236 | __libcpp_mutex_unlock(&mut);
|
| 237 | + __libcpp_condvar_broadcast(&cv); |
| 238 | + guard.__complete(); |
| 239 | + } else { |
| 240 | + __libcpp_mutex_unlock(&mut); |
| 241 | + } |
| 242 | + |
258 | 243 | #endif // !_LIBCPP_HAS_NO_THREADS
|
259 | 244 | }
|
260 | 245 |
|
|
0 commit comments