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/core/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 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 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 { BOOST_THREAD_NO_COPYABLEboost::once_flag61 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 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 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 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 122 123 124 template<typename Function, class ...ArgTypes> call_once(once_flag & flag,BOOST_THREAD_RV_REF (Function)f,BOOST_THREAD_RV_REF (ArgTypes)...args)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> call_once(once_flag & flag,Function f)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> call_once(once_flag & flag,Function f,T1 p1)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> call_once(once_flag & flag,Function f,T1 p1,T2 p2)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> call_once(once_flag & flag,Function f,T1 p1,T2 p2,T3 p3)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> call_once(once_flag & flag,BOOST_THREAD_RV_REF (Function)f)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> call_once(once_flag & flag,BOOST_THREAD_RV_REF (Function)f,BOOST_THREAD_RV_REF (T1)p1)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> call_once(once_flag & flag,BOOST_THREAD_RV_REF (Function)f,BOOST_THREAD_RV_REF (T1)p1,BOOST_THREAD_RV_REF (T2)p2)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> 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)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 541