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