Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/thread/pthread/once.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 #ifndef BOOST_THREAD_PTHREAD_ONCE_HPP | |
2 #define BOOST_THREAD_PTHREAD_ONCE_HPP | |
3 | |
4 // once.hpp | |
5 // | |
6 // (C) Copyright 2007-8 Anthony Williams | |
7 // (C) Copyright 2011-2012 Vicente J. Botet Escriba | |
8 // | |
9 // Distributed under the Boost Software License, Version 1.0. (See | |
10 // accompanying file LICENSE_1_0.txt or copy at | |
11 // http://www.boost.org/LICENSE_1_0.txt) | |
12 | |
13 #include <boost/thread/detail/config.hpp> | |
14 #include <boost/thread/detail/move.hpp> | |
15 #include <boost/thread/detail/invoke.hpp> | |
16 | |
17 #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> | |
18 #include <boost/thread/detail/delete.hpp> | |
19 #include <boost/detail/no_exceptions_support.hpp> | |
20 | |
21 #include <boost/bind.hpp> | |
22 #include <boost/assert.hpp> | |
23 #include <boost/config/abi_prefix.hpp> | |
24 | |
25 #include <boost/cstdint.hpp> | |
26 #include <pthread.h> | |
27 #include <csignal> | |
28 | |
29 namespace boost | |
30 { | |
31 | |
32 struct once_flag; | |
33 | |
34 #define BOOST_ONCE_INITIAL_FLAG_VALUE 0 | |
35 | |
36 namespace thread_detail | |
37 { | |
38 typedef boost::uint32_t uintmax_atomic_t; | |
39 #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(value) value##u | |
40 #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(~0) | |
41 | |
42 } | |
43 | |
44 #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 | |
45 #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES | |
46 template<typename Function, class ...ArgTypes> | |
47 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args); | |
48 #else | |
49 template<typename Function> | |
50 inline void call_once(once_flag& flag, Function f); | |
51 template<typename Function, typename T1> | |
52 inline void call_once(once_flag& flag, Function f, T1 p1); | |
53 template<typename Function, typename T1, typename T2> | |
54 inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2); | |
55 template<typename Function, typename T1, typename T2, typename T3> | |
56 inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3); | |
57 #endif | |
58 | |
59 struct once_flag | |
60 { | |
61 BOOST_THREAD_NO_COPYABLE(once_flag) | |
62 BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT | |
63 : epoch(BOOST_ONCE_INITIAL_FLAG_VALUE) | |
64 {} | |
65 private: | |
66 volatile thread_detail::uintmax_atomic_t epoch; | |
67 | |
68 #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES | |
69 template<typename Function, class ...ArgTypes> | |
70 friend void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args); | |
71 #else | |
72 template<typename Function> | |
73 friend void call_once(once_flag& flag, Function f); | |
74 template<typename Function, typename T1> | |
75 friend void call_once(once_flag& flag, Function f, T1 p1); | |
76 template<typename Function, typename T1, typename T2> | |
77 friend void call_once(once_flag& flag, Function f, T1 p1, T2 p2); | |
78 template<typename Function, typename T1, typename T2, typename T3> | |
79 friend void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3); | |
80 | |
81 #endif | |
82 | |
83 }; | |
84 | |
85 #define BOOST_ONCE_INIT once_flag() | |
86 | |
87 #else // BOOST_THREAD_PROVIDES_ONCE_CXX11 | |
88 | |
89 struct once_flag | |
90 { | |
91 volatile thread_detail::uintmax_atomic_t epoch; | |
92 }; | |
93 | |
94 #define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE} | |
95 #endif // BOOST_THREAD_PROVIDES_ONCE_CXX11 | |
96 | |
97 | |
98 #if defined BOOST_THREAD_PROVIDES_INVOKE | |
99 #define BOOST_THREAD_INVOKE_RET_VOID detail::invoke | |
100 #define BOOST_THREAD_INVOKE_RET_VOID_CALL | |
101 #elif defined BOOST_THREAD_PROVIDES_INVOKE_RET | |
102 #define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void> | |
103 #define BOOST_THREAD_INVOKE_RET_VOID_CALL | |
104 #else | |
105 #define BOOST_THREAD_INVOKE_RET_VOID boost::bind | |
106 #define BOOST_THREAD_INVOKE_RET_VOID_CALL () | |
107 #endif | |
108 | |
109 namespace thread_detail | |
110 { | |
111 BOOST_THREAD_DECL uintmax_atomic_t& get_once_per_thread_epoch(); | |
112 BOOST_THREAD_DECL extern uintmax_atomic_t once_global_epoch; | |
113 BOOST_THREAD_DECL extern pthread_mutex_t once_epoch_mutex; | |
114 BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv; | |
115 } | |
116 | |
117 // Based on Mike Burrows fast_pthread_once algorithm as described in | |
118 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html | |
119 | |
120 | |
121 #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES | |
122 | |
123 | |
124 template<typename Function, class ...ArgTypes> | |
125 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args) | |
126 { | |
127 static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; | |
128 static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; | |
129 thread_detail::uintmax_atomic_t const epoch=flag.epoch; | |
130 thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); | |
131 | |
132 if(epoch<this_thread_epoch) | |
133 { | |
134 pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); | |
135 | |
136 while(flag.epoch<=being_initialized) | |
137 { | |
138 if(flag.epoch==uninitialized_flag) | |
139 { | |
140 flag.epoch=being_initialized; | |
141 BOOST_TRY | |
142 { | |
143 pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); | |
144 BOOST_THREAD_INVOKE_RET_VOID( | |
145 thread_detail::decay_copy(boost::forward<Function>(f)), | |
146 thread_detail::decay_copy(boost::forward<ArgTypes>(args))... | |
147 ) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
148 } | |
149 BOOST_CATCH (...) | |
150 { | |
151 flag.epoch=uninitialized_flag; | |
152 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
153 BOOST_RETHROW | |
154 } | |
155 BOOST_CATCH_END | |
156 flag.epoch=--thread_detail::once_global_epoch; | |
157 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
158 } | |
159 else | |
160 { | |
161 while(flag.epoch==being_initialized) | |
162 { | |
163 BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); | |
164 } | |
165 } | |
166 } | |
167 this_thread_epoch=thread_detail::once_global_epoch; | |
168 | |
169 } | |
170 } | |
171 #else | |
172 template<typename Function> | |
173 inline void call_once(once_flag& flag, Function f) | |
174 { | |
175 static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; | |
176 static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; | |
177 thread_detail::uintmax_atomic_t const epoch=flag.epoch; | |
178 thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); | |
179 | |
180 if(epoch<this_thread_epoch) | |
181 { | |
182 pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); | |
183 | |
184 while(flag.epoch<=being_initialized) | |
185 { | |
186 if(flag.epoch==uninitialized_flag) | |
187 { | |
188 flag.epoch=being_initialized; | |
189 BOOST_TRY | |
190 { | |
191 pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); | |
192 f(); | |
193 } | |
194 BOOST_CATCH (...) | |
195 { | |
196 flag.epoch=uninitialized_flag; | |
197 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
198 BOOST_RETHROW | |
199 } | |
200 BOOST_CATCH_END | |
201 flag.epoch=--thread_detail::once_global_epoch; | |
202 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
203 } | |
204 else | |
205 { | |
206 while(flag.epoch==being_initialized) | |
207 { | |
208 BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); | |
209 } | |
210 } | |
211 } | |
212 this_thread_epoch=thread_detail::once_global_epoch; | |
213 } | |
214 } | |
215 | |
216 template<typename Function, typename T1> | |
217 inline void call_once(once_flag& flag, Function f, T1 p1) | |
218 { | |
219 static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; | |
220 static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; | |
221 thread_detail::uintmax_atomic_t const epoch=flag.epoch; | |
222 thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); | |
223 | |
224 if(epoch<this_thread_epoch) | |
225 { | |
226 pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); | |
227 | |
228 while(flag.epoch<=being_initialized) | |
229 { | |
230 if(flag.epoch==uninitialized_flag) | |
231 { | |
232 flag.epoch=being_initialized; | |
233 BOOST_TRY | |
234 { | |
235 pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); | |
236 BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
237 } | |
238 BOOST_CATCH (...) | |
239 { | |
240 flag.epoch=uninitialized_flag; | |
241 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
242 BOOST_RETHROW | |
243 } | |
244 BOOST_CATCH_END | |
245 flag.epoch=--thread_detail::once_global_epoch; | |
246 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
247 } | |
248 else | |
249 { | |
250 while(flag.epoch==being_initialized) | |
251 { | |
252 BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); | |
253 } | |
254 } | |
255 } | |
256 this_thread_epoch=thread_detail::once_global_epoch; | |
257 } | |
258 } | |
259 template<typename Function, typename T1, typename T2> | |
260 inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2) | |
261 { | |
262 static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; | |
263 static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; | |
264 thread_detail::uintmax_atomic_t const epoch=flag.epoch; | |
265 thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); | |
266 | |
267 if(epoch<this_thread_epoch) | |
268 { | |
269 pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); | |
270 | |
271 while(flag.epoch<=being_initialized) | |
272 { | |
273 if(flag.epoch==uninitialized_flag) | |
274 { | |
275 flag.epoch=being_initialized; | |
276 BOOST_TRY | |
277 { | |
278 pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); | |
279 BOOST_THREAD_INVOKE_RET_VOID(f,p1, p2) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
280 } | |
281 BOOST_CATCH (...) | |
282 { | |
283 flag.epoch=uninitialized_flag; | |
284 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
285 BOOST_RETHROW | |
286 } | |
287 BOOST_CATCH_END | |
288 flag.epoch=--thread_detail::once_global_epoch; | |
289 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
290 } | |
291 else | |
292 { | |
293 while(flag.epoch==being_initialized) | |
294 { | |
295 BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); | |
296 } | |
297 } | |
298 } | |
299 this_thread_epoch=thread_detail::once_global_epoch; | |
300 } | |
301 } | |
302 | |
303 template<typename Function, typename T1, typename T2, typename T3> | |
304 inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3) | |
305 { | |
306 static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; | |
307 static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; | |
308 thread_detail::uintmax_atomic_t const epoch=flag.epoch; | |
309 thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); | |
310 | |
311 if(epoch<this_thread_epoch) | |
312 { | |
313 pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); | |
314 | |
315 while(flag.epoch<=being_initialized) | |
316 { | |
317 if(flag.epoch==uninitialized_flag) | |
318 { | |
319 flag.epoch=being_initialized; | |
320 BOOST_TRY | |
321 { | |
322 pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); | |
323 BOOST_THREAD_INVOKE_RET_VOID(f,p1, p2, p3) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
324 } | |
325 BOOST_CATCH (...) | |
326 { | |
327 flag.epoch=uninitialized_flag; | |
328 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
329 BOOST_RETHROW | |
330 } | |
331 BOOST_CATCH_END | |
332 flag.epoch=--thread_detail::once_global_epoch; | |
333 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
334 } | |
335 else | |
336 { | |
337 while(flag.epoch==being_initialized) | |
338 { | |
339 BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); | |
340 } | |
341 } | |
342 } | |
343 this_thread_epoch=thread_detail::once_global_epoch; | |
344 } | |
345 } | |
346 | |
347 template<typename Function> | |
348 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f) | |
349 { | |
350 static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; | |
351 static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; | |
352 thread_detail::uintmax_atomic_t const epoch=flag.epoch; | |
353 thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); | |
354 | |
355 if(epoch<this_thread_epoch) | |
356 { | |
357 pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); | |
358 | |
359 while(flag.epoch<=being_initialized) | |
360 { | |
361 if(flag.epoch==uninitialized_flag) | |
362 { | |
363 flag.epoch=being_initialized; | |
364 BOOST_TRY | |
365 { | |
366 pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); | |
367 f(); | |
368 } | |
369 BOOST_CATCH (...) | |
370 { | |
371 flag.epoch=uninitialized_flag; | |
372 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
373 BOOST_RETHROW | |
374 } | |
375 BOOST_CATCH_END | |
376 flag.epoch=--thread_detail::once_global_epoch; | |
377 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
378 } | |
379 else | |
380 { | |
381 while(flag.epoch==being_initialized) | |
382 { | |
383 BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); | |
384 } | |
385 } | |
386 } | |
387 this_thread_epoch=thread_detail::once_global_epoch; | |
388 } | |
389 } | |
390 | |
391 template<typename Function, typename T1> | |
392 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1) | |
393 { | |
394 static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; | |
395 static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; | |
396 thread_detail::uintmax_atomic_t const epoch=flag.epoch; | |
397 thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); | |
398 | |
399 if(epoch<this_thread_epoch) | |
400 { | |
401 pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); | |
402 | |
403 while(flag.epoch<=being_initialized) | |
404 { | |
405 if(flag.epoch==uninitialized_flag) | |
406 { | |
407 flag.epoch=being_initialized; | |
408 BOOST_TRY | |
409 { | |
410 pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); | |
411 BOOST_THREAD_INVOKE_RET_VOID( | |
412 thread_detail::decay_copy(boost::forward<Function>(f)), | |
413 thread_detail::decay_copy(boost::forward<T1>(p1)) | |
414 ) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
415 } | |
416 BOOST_CATCH (...) | |
417 { | |
418 flag.epoch=uninitialized_flag; | |
419 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
420 BOOST_RETHROW | |
421 } | |
422 BOOST_CATCH_END | |
423 flag.epoch=--thread_detail::once_global_epoch; | |
424 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
425 } | |
426 else | |
427 { | |
428 while(flag.epoch==being_initialized) | |
429 { | |
430 BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); | |
431 } | |
432 } | |
433 } | |
434 this_thread_epoch=thread_detail::once_global_epoch; | |
435 } | |
436 } | |
437 template<typename Function, typename T1, typename T2> | |
438 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2) | |
439 { | |
440 static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; | |
441 static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; | |
442 thread_detail::uintmax_atomic_t const epoch=flag.epoch; | |
443 thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); | |
444 | |
445 if(epoch<this_thread_epoch) | |
446 { | |
447 pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); | |
448 | |
449 while(flag.epoch<=being_initialized) | |
450 { | |
451 if(flag.epoch==uninitialized_flag) | |
452 { | |
453 flag.epoch=being_initialized; | |
454 BOOST_TRY | |
455 { | |
456 pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); | |
457 BOOST_THREAD_INVOKE_RET_VOID( | |
458 thread_detail::decay_copy(boost::forward<Function>(f)), | |
459 thread_detail::decay_copy(boost::forward<T1>(p1)), | |
460 thread_detail::decay_copy(boost::forward<T1>(p2)) | |
461 ) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
462 } | |
463 BOOST_CATCH (...) | |
464 { | |
465 flag.epoch=uninitialized_flag; | |
466 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
467 BOOST_RETHROW | |
468 } | |
469 BOOST_CATCH_END | |
470 flag.epoch=--thread_detail::once_global_epoch; | |
471 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
472 } | |
473 else | |
474 { | |
475 while(flag.epoch==being_initialized) | |
476 { | |
477 BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); | |
478 } | |
479 } | |
480 } | |
481 this_thread_epoch=thread_detail::once_global_epoch; | |
482 } | |
483 } | |
484 | |
485 template<typename Function, typename T1, typename T2, typename T3> | |
486 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3) | |
487 { | |
488 static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; | |
489 static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; | |
490 thread_detail::uintmax_atomic_t const epoch=flag.epoch; | |
491 thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); | |
492 | |
493 if(epoch<this_thread_epoch) | |
494 { | |
495 pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); | |
496 | |
497 while(flag.epoch<=being_initialized) | |
498 { | |
499 if(flag.epoch==uninitialized_flag) | |
500 { | |
501 flag.epoch=being_initialized; | |
502 BOOST_TRY | |
503 { | |
504 pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); | |
505 BOOST_THREAD_INVOKE_RET_VOID( | |
506 thread_detail::decay_copy(boost::forward<Function>(f)), | |
507 thread_detail::decay_copy(boost::forward<T1>(p1)), | |
508 thread_detail::decay_copy(boost::forward<T1>(p2)), | |
509 thread_detail::decay_copy(boost::forward<T1>(p3)) | |
510 ) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
511 } | |
512 BOOST_CATCH (...) | |
513 { | |
514 flag.epoch=uninitialized_flag; | |
515 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
516 BOOST_RETHROW | |
517 } | |
518 BOOST_CATCH_END | |
519 flag.epoch=--thread_detail::once_global_epoch; | |
520 BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); | |
521 } | |
522 else | |
523 { | |
524 while(flag.epoch==being_initialized) | |
525 { | |
526 BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); | |
527 } | |
528 } | |
529 } | |
530 this_thread_epoch=thread_detail::once_global_epoch; | |
531 } | |
532 } | |
533 | |
534 #endif | |
535 | |
536 } | |
537 | |
538 #include <boost/config/abi_suffix.hpp> | |
539 | |
540 #endif |