File indexing completed on 2025-12-16 10:10:03
0001 #ifndef BOOST_THREAD_WIN32_ONCE_HPP
0002 #define BOOST_THREAD_WIN32_ONCE_HPP
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <cstring>
0015 #include <cstddef>
0016 #include <boost/assert.hpp>
0017 #include <boost/static_assert.hpp>
0018 #include <boost/detail/interlocked.hpp>
0019 #include <boost/thread/win32/thread_primitives.hpp>
0020 #include <boost/thread/win32/interlocked_read.hpp>
0021 #include <boost/core/no_exceptions_support.hpp>
0022 #include <boost/thread/detail/move.hpp>
0023 #include <boost/thread/detail/invoke.hpp>
0024
0025 #include <boost/bind/bind.hpp>
0026
0027 #include <boost/config/abi_prefix.hpp>
0028
0029 #ifdef BOOST_NO_STDC_NAMESPACE
0030 namespace std
0031 {
0032 using ::memcpy;
0033 using ::ptrdiff_t;
0034 }
0035 #endif
0036
0037 namespace boost
0038 {
0039 struct once_flag;
0040 namespace detail
0041 {
0042 struct once_context;
0043
0044 inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT;
0045 inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT;
0046 inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT;
0047 }
0048
0049 #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
0050
0051 struct once_flag
0052 {
0053 BOOST_THREAD_NO_COPYABLE(once_flag)
0054 BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT
0055 : status(0), count(0)
0056 {}
0057 long status;
0058 long count;
0059 private:
0060 friend inline bool enter_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT;
0061 friend inline void commit_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT;
0062 friend inline void rollback_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT;
0063 };
0064
0065 #define BOOST_ONCE_INIT once_flag()
0066 #else
0067
0068 struct once_flag
0069 {
0070 long status;
0071 long count;
0072 };
0073
0074 #define BOOST_ONCE_INIT {0,0}
0075 #endif
0076
0077 #if defined BOOST_THREAD_PROVIDES_INVOKE
0078 #define BOOST_THREAD_INVOKE_RET_VOID detail::invoke
0079 #define BOOST_THREAD_INVOKE_RET_VOID_CALL
0080 #elif defined BOOST_THREAD_PROVIDES_INVOKE_RET
0081 #define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void>
0082 #define BOOST_THREAD_INVOKE_RET_VOID_CALL
0083 #else
0084 #define BOOST_THREAD_INVOKE_RET_VOID boost::bind
0085 #define BOOST_THREAD_INVOKE_RET_VOID_CALL ()
0086 #endif
0087
0088 namespace detail
0089 {
0090 #ifdef BOOST_NO_ANSI_APIS
0091 typedef wchar_t once_char_type;
0092 #else
0093 typedef char once_char_type;
0094 #endif
0095 unsigned const once_mutex_name_fixed_length=54;
0096 unsigned const once_mutex_name_length=once_mutex_name_fixed_length+
0097 sizeof(void*)*2+sizeof(unsigned long)*2+1;
0098
0099 template <class I>
0100 void int_to_string(I p, once_char_type* buf)
0101 {
0102 for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
0103 {
0104 #ifdef BOOST_NO_ANSI_APIS
0105 once_char_type const a=L'A';
0106 #else
0107 once_char_type const a='A';
0108 #endif
0109 *buf = a + static_cast<once_char_type>((p >> (i*4)) & 0x0f);
0110 }
0111 *buf = 0;
0112 }
0113
0114 inline void name_once_mutex(once_char_type* mutex_name,void* flag_address)
0115 {
0116 #ifdef BOOST_NO_ANSI_APIS
0117 static const once_char_type fixed_mutex_name[]=L"Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
0118 #else
0119 static const once_char_type fixed_mutex_name[]="Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
0120 #endif
0121 BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) ==
0122 (sizeof(once_char_type)*(once_mutex_name_fixed_length+1)));
0123
0124 std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name));
0125 detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address),
0126 mutex_name + once_mutex_name_fixed_length);
0127 detail::int_to_string(winapi::GetCurrentProcessId(),
0128 mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2);
0129 }
0130
0131 inline void* open_once_event(once_char_type* mutex_name,void* flag_address)
0132 {
0133 if(!*mutex_name)
0134 {
0135 name_once_mutex(mutex_name,flag_address);
0136 }
0137
0138 #ifdef BOOST_NO_ANSI_APIS
0139 return ::boost::winapi::OpenEventW(
0140 #else
0141 return ::boost::winapi::OpenEventA(
0142 #endif
0143 ::boost::detail::win32::synchronize |
0144 ::boost::detail::win32::event_modify_state,
0145 false,
0146 mutex_name);
0147 }
0148
0149 inline void* create_once_event(once_char_type* mutex_name,void* flag_address)
0150 {
0151 if(!*mutex_name)
0152 {
0153 name_once_mutex(mutex_name,flag_address);
0154 }
0155
0156 return ::boost::detail::win32::create_event(
0157 mutex_name,
0158 ::boost::detail::win32::manual_reset_event,
0159 ::boost::detail::win32::event_initially_reset);
0160 }
0161
0162 struct once_context {
0163 long const function_complete_flag_value;
0164 long const running_value;
0165 bool counted;
0166 detail::win32::handle_manager event_handle;
0167 detail::once_char_type mutex_name[once_mutex_name_length];
0168 once_context() :
0169 function_complete_flag_value(0xc15730e2),
0170 running_value(0x7f0725e3),
0171 counted(false)
0172 {
0173 mutex_name[0]=0;
0174 }
0175 };
0176 enum once_action {try_, break_, continue_};
0177
0178 inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
0179 {
0180 long status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,ctx.running_value,0);
0181 if(!status)
0182 {
0183 if(!ctx.event_handle)
0184 {
0185 ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag);
0186 }
0187 if(ctx.event_handle)
0188 {
0189 ::boost::winapi::ResetEvent(ctx.event_handle);
0190 }
0191 return true;
0192 }
0193 return false;
0194 }
0195 inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
0196 {
0197 if(!ctx.counted)
0198 {
0199 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0200 ctx.counted=true;
0201 }
0202 BOOST_INTERLOCKED_EXCHANGE(&flag.status,ctx.function_complete_flag_value);
0203 if(!ctx.event_handle &&
0204 (::boost::detail::interlocked_read_acquire(&flag.count)>1))
0205 {
0206 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0207 }
0208 if(ctx.event_handle)
0209 {
0210 ::boost::winapi::SetEvent(ctx.event_handle);
0211 }
0212 }
0213 inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
0214 {
0215 BOOST_INTERLOCKED_EXCHANGE(&flag.status,0);
0216 if(!ctx.event_handle)
0217 {
0218 ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag);
0219 }
0220 if(ctx.event_handle)
0221 {
0222 ::boost::winapi::SetEvent(ctx.event_handle);
0223 }
0224 }
0225 }
0226
0227 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0228
0229 inline void call_once(once_flag& flag, void (*f)())
0230 {
0231
0232
0233 detail::once_context ctx;
0234 while(::boost::detail::interlocked_read_acquire(&flag.status)
0235 !=ctx.function_complete_flag_value)
0236 {
0237 if(detail::enter_once_region(flag, ctx))
0238 {
0239 BOOST_TRY
0240 {
0241 f();
0242 }
0243 BOOST_CATCH(...)
0244 {
0245 detail::rollback_once_region(flag, ctx);
0246 BOOST_RETHROW
0247 }
0248 BOOST_CATCH_END
0249 detail::commit_once_region(flag, ctx);
0250 break;
0251 }
0252 if(!ctx.counted)
0253 {
0254 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0255 ctx.counted=true;
0256 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0257 if(status==ctx.function_complete_flag_value)
0258 {
0259 break;
0260 }
0261 if(!ctx.event_handle)
0262 {
0263 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0264 continue;
0265 }
0266 }
0267 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0268 ctx.event_handle,::boost::detail::win32::infinite, 0));
0269 }
0270 }
0271
0272 template<typename Function>
0273 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f)
0274 {
0275
0276
0277 detail::once_context ctx;
0278 while(::boost::detail::interlocked_read_acquire(&flag.status)
0279 !=ctx.function_complete_flag_value)
0280 {
0281 if(detail::enter_once_region(flag, ctx))
0282 {
0283 BOOST_TRY
0284 {
0285 f();
0286 }
0287 BOOST_CATCH(...)
0288 {
0289 detail::rollback_once_region(flag, ctx);
0290 BOOST_RETHROW
0291 }
0292 BOOST_CATCH_END
0293 detail::commit_once_region(flag, ctx);
0294 break;
0295 }
0296 if(!ctx.counted)
0297 {
0298 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0299 ctx.counted=true;
0300 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0301 if(status==ctx.function_complete_flag_value)
0302 {
0303 break;
0304 }
0305 if(!ctx.event_handle)
0306 {
0307 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0308 continue;
0309 }
0310 }
0311 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0312 ctx.event_handle,::boost::detail::win32::infinite,0));
0313 }
0314 }
0315 template<typename Function, class A, class ...ArgTypes>
0316 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(A) a, BOOST_THREAD_RV_REF(ArgTypes)... args)
0317 {
0318
0319
0320 detail::once_context ctx;
0321 while(::boost::detail::interlocked_read_acquire(&flag.status)
0322 !=ctx.function_complete_flag_value)
0323 {
0324 if(detail::enter_once_region(flag, ctx))
0325 {
0326 BOOST_TRY
0327 {
0328 BOOST_THREAD_INVOKE_RET_VOID(
0329 thread_detail::decay_copy(boost::forward<Function>(f)),
0330 thread_detail::decay_copy(boost::forward<A>(a)),
0331 thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
0332 ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
0333 }
0334 BOOST_CATCH(...)
0335 {
0336 detail::rollback_once_region(flag, ctx);
0337 BOOST_RETHROW
0338 }
0339 BOOST_CATCH_END
0340 detail::commit_once_region(flag, ctx);
0341 break;
0342 }
0343 if(!ctx.counted)
0344 {
0345 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0346 ctx.counted=true;
0347 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0348 if(status==ctx.function_complete_flag_value)
0349 {
0350 break;
0351 }
0352 if(!ctx.event_handle)
0353 {
0354 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0355 continue;
0356 }
0357 }
0358 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0359 ctx.event_handle,::boost::detail::win32::infinite,0));
0360 }
0361 }
0362 #else
0363 #if ! defined(BOOST_MSVC) && ! defined(BOOST_INTEL)
0364 template<typename Function>
0365 void call_once(once_flag& flag,Function f)
0366 {
0367
0368
0369 detail::once_context ctx;
0370 while(::boost::detail::interlocked_read_acquire(&flag.status)
0371 !=ctx.function_complete_flag_value)
0372 {
0373 if(detail::enter_once_region(flag, ctx))
0374 {
0375 BOOST_TRY
0376 {
0377 f();
0378 }
0379 BOOST_CATCH(...)
0380 {
0381 detail::rollback_once_region(flag, ctx);
0382 BOOST_RETHROW
0383 }
0384 BOOST_CATCH_END
0385 detail::commit_once_region(flag, ctx);
0386 break;
0387 }
0388 if(!ctx.counted)
0389 {
0390 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0391 ctx.counted=true;
0392 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0393 if(status==ctx.function_complete_flag_value)
0394 {
0395 break;
0396 }
0397 if(!ctx.event_handle)
0398 {
0399 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0400 continue;
0401 }
0402 }
0403 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0404 ctx.event_handle,::boost::detail::win32::infinite,0));
0405 }
0406 }
0407 template<typename Function, typename T1>
0408 void call_once(once_flag& flag,Function f, T1 p1)
0409 {
0410
0411
0412 detail::once_context ctx;
0413 while(::boost::detail::interlocked_read_acquire(&flag.status)
0414 !=ctx.function_complete_flag_value)
0415 {
0416 if(detail::enter_once_region(flag, ctx))
0417 {
0418 BOOST_TRY
0419 {
0420 BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL;
0421 }
0422 BOOST_CATCH(...)
0423 {
0424 detail::rollback_once_region(flag, ctx);
0425 BOOST_RETHROW
0426 }
0427 BOOST_CATCH_END
0428 detail::commit_once_region(flag, ctx);
0429 break;
0430 }
0431 if(!ctx.counted)
0432 {
0433 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0434 ctx.counted=true;
0435 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0436 if(status==ctx.function_complete_flag_value)
0437 {
0438 break;
0439 }
0440 if(!ctx.event_handle)
0441 {
0442 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0443 continue;
0444 }
0445 }
0446 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0447 ctx.event_handle,::boost::detail::win32::infinite,0));
0448 }
0449 }
0450 template<typename Function, typename T1, typename T2>
0451 void call_once(once_flag& flag,Function f, T1 p1, T2 p2)
0452 {
0453
0454
0455 detail::once_context ctx;
0456 while(::boost::detail::interlocked_read_acquire(&flag.status)
0457 !=ctx.function_complete_flag_value)
0458 {
0459 if(detail::enter_once_region(flag, ctx))
0460 {
0461 BOOST_TRY
0462 {
0463 BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2) BOOST_THREAD_INVOKE_RET_VOID_CALL;
0464 }
0465 BOOST_CATCH(...)
0466 {
0467 detail::rollback_once_region(flag, ctx);
0468 BOOST_RETHROW
0469 }
0470 BOOST_CATCH_END
0471 detail::commit_once_region(flag, ctx);
0472 break;
0473 }
0474 if(!ctx.counted)
0475 {
0476 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0477 ctx.counted=true;
0478 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0479 if(status==ctx.function_complete_flag_value)
0480 {
0481 break;
0482 }
0483 if(!ctx.event_handle)
0484 {
0485 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0486 continue;
0487 }
0488 }
0489 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0490 ctx.event_handle,::boost::detail::win32::infinite,0));
0491 }
0492 }
0493 template<typename Function, typename T1, typename T2, typename T3>
0494 void call_once(once_flag& flag,Function f, T1 p1, T2 p2, T3 p3)
0495 {
0496
0497
0498 detail::once_context ctx;
0499 while(::boost::detail::interlocked_read_acquire(&flag.status)
0500 !=ctx.function_complete_flag_value)
0501 {
0502 if(detail::enter_once_region(flag, ctx))
0503 {
0504 BOOST_TRY
0505 {
0506 BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2,p3) BOOST_THREAD_INVOKE_RET_VOID_CALL;
0507 }
0508 BOOST_CATCH(...)
0509 {
0510 detail::rollback_once_region(flag, ctx);
0511 BOOST_RETHROW
0512 }
0513 BOOST_CATCH_END
0514 detail::commit_once_region(flag, ctx);
0515 break;
0516 }
0517 if(!ctx.counted)
0518 {
0519 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0520 ctx.counted=true;
0521 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0522 if(status==ctx.function_complete_flag_value)
0523 {
0524 break;
0525 }
0526 if(!ctx.event_handle)
0527 {
0528 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0529 continue;
0530 }
0531 }
0532 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0533 ctx.event_handle,::boost::detail::win32::infinite,0));
0534 }
0535 }
0536 #elif defined BOOST_NO_CXX11_RVALUE_REFERENCES
0537
0538 template<typename Function>
0539 void call_once(once_flag& flag,Function const&f)
0540 {
0541
0542
0543 detail::once_context ctx;
0544 while(::boost::detail::interlocked_read_acquire(&flag.status)
0545 !=ctx.function_complete_flag_value)
0546 {
0547 if(detail::enter_once_region(flag, ctx))
0548 {
0549 BOOST_TRY
0550 {
0551 f();
0552 }
0553 BOOST_CATCH(...)
0554 {
0555 detail::rollback_once_region(flag, ctx);
0556 BOOST_RETHROW
0557 }
0558 BOOST_CATCH_END
0559 detail::commit_once_region(flag, ctx);
0560 break;
0561 }
0562 if(!ctx.counted)
0563 {
0564 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0565 ctx.counted=true;
0566 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0567 if(status==ctx.function_complete_flag_value)
0568 {
0569 break;
0570 }
0571 if(!ctx.event_handle)
0572 {
0573 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0574 continue;
0575 }
0576 }
0577 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0578 ctx.event_handle,::boost::detail::win32::infinite,0));
0579 }
0580 }
0581 template<typename Function, typename T1>
0582 void call_once(once_flag& flag,Function const&f, T1 const&p1)
0583 {
0584
0585
0586 detail::once_context ctx;
0587 while(::boost::detail::interlocked_read_acquire(&flag.status)
0588 !=ctx.function_complete_flag_value)
0589 {
0590 if(detail::enter_once_region(flag, ctx))
0591 {
0592 BOOST_TRY
0593 {
0594 BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL;
0595 }
0596 BOOST_CATCH(...)
0597 {
0598 detail::rollback_once_region(flag, ctx);
0599 BOOST_RETHROW
0600 }
0601 BOOST_CATCH_END
0602 detail::commit_once_region(flag, ctx);
0603 break;
0604 }
0605 if(!ctx.counted)
0606 {
0607 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0608 ctx.counted=true;
0609 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0610 if(status==ctx.function_complete_flag_value)
0611 {
0612 break;
0613 }
0614 if(!ctx.event_handle)
0615 {
0616 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0617 continue;
0618 }
0619 }
0620 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0621 ctx.event_handle,::boost::detail::win32::infinite,0));
0622 }
0623 }
0624 template<typename Function, typename T1, typename T2>
0625 void call_once(once_flag& flag,Function const&f, T1 const&p1, T2 const&p2)
0626 {
0627
0628
0629 detail::once_context ctx;
0630 while(::boost::detail::interlocked_read_acquire(&flag.status)
0631 !=ctx.function_complete_flag_value)
0632 {
0633 if(detail::enter_once_region(flag, ctx))
0634 {
0635 BOOST_TRY
0636 {
0637 BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2) BOOST_THREAD_INVOKE_RET_VOID_CALL;
0638 }
0639 BOOST_CATCH(...)
0640 {
0641 detail::rollback_once_region(flag, ctx);
0642 BOOST_RETHROW
0643 }
0644 BOOST_CATCH_END
0645 detail::commit_once_region(flag, ctx);
0646 break;
0647 }
0648 if(!ctx.counted)
0649 {
0650 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0651 ctx.counted=true;
0652 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0653 if(status==ctx.function_complete_flag_value)
0654 {
0655 break;
0656 }
0657 if(!ctx.event_handle)
0658 {
0659 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0660 continue;
0661 }
0662 }
0663 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0664 ctx.event_handle,::boost::detail::win32::infinite,0));
0665 }
0666 }
0667 template<typename Function, typename T1, typename T2, typename T3>
0668 void call_once(once_flag& flag,Function const&f, T1 const&p1, T2 const&p2, T3 const&p3)
0669 {
0670
0671
0672 detail::once_context ctx;
0673 while(::boost::detail::interlocked_read_acquire(&flag.status)
0674 !=ctx.function_complete_flag_value)
0675 {
0676 if(detail::enter_once_region(flag, ctx))
0677 {
0678 BOOST_TRY
0679 {
0680 BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2,p3) BOOST_THREAD_INVOKE_RET_VOID_CALL;
0681 }
0682 BOOST_CATCH(...)
0683 {
0684 detail::rollback_once_region(flag, ctx);
0685 BOOST_RETHROW
0686 }
0687 BOOST_CATCH_END
0688 detail::commit_once_region(flag, ctx);
0689 break;
0690 }
0691 if(!ctx.counted)
0692 {
0693 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0694 ctx.counted=true;
0695 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0696 if(status==ctx.function_complete_flag_value)
0697 {
0698 break;
0699 }
0700 if(!ctx.event_handle)
0701 {
0702 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0703 continue;
0704 }
0705 }
0706 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0707 ctx.event_handle,::boost::detail::win32::infinite,0));
0708 }
0709 }
0710 #endif
0711 #if 1
0712 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
0713 inline void call_once(once_flag& flag, void (*f)())
0714 {
0715
0716
0717 detail::once_context ctx;
0718 while(::boost::detail::interlocked_read_acquire(&flag.status)
0719 !=ctx.function_complete_flag_value)
0720 {
0721 if(detail::enter_once_region(flag, ctx))
0722 {
0723 BOOST_TRY
0724 {
0725 f();
0726 }
0727 BOOST_CATCH(...)
0728 {
0729 detail::rollback_once_region(flag, ctx);
0730 BOOST_RETHROW
0731 }
0732 BOOST_CATCH_END
0733 detail::commit_once_region(flag, ctx);
0734 break;
0735 }
0736 if(!ctx.counted)
0737 {
0738 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0739 ctx.counted=true;
0740 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0741 if(status==ctx.function_complete_flag_value)
0742 {
0743 break;
0744 }
0745 if(!ctx.event_handle)
0746 {
0747 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0748 continue;
0749 }
0750 }
0751 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0752 ctx.event_handle,::boost::detail::win32::infinite,0));
0753 }
0754 }
0755 template<typename T1>
0756 void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1)), BOOST_THREAD_RV_REF(T1) p1)
0757 {
0758
0759
0760 detail::once_context ctx;
0761 while(::boost::detail::interlocked_read_acquire(&flag.status)
0762 !=ctx.function_complete_flag_value)
0763 {
0764 if(detail::enter_once_region(flag, ctx))
0765 {
0766 BOOST_TRY
0767 {
0768 f(
0769 thread_detail::decay_copy(boost::forward<T1>(p1))
0770 );
0771 }
0772 BOOST_CATCH(...)
0773 {
0774 detail::rollback_once_region(flag, ctx);
0775 BOOST_RETHROW
0776 }
0777 BOOST_CATCH_END
0778 detail::commit_once_region(flag, ctx);
0779 break;
0780 }
0781 if(!ctx.counted)
0782 {
0783 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0784 ctx.counted=true;
0785 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0786 if(status==ctx.function_complete_flag_value)
0787 {
0788 break;
0789 }
0790 if(!ctx.event_handle)
0791 {
0792 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0793 continue;
0794 }
0795 }
0796 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0797 ctx.event_handle,::boost::detail::win32::infinite,0));
0798 }
0799 }
0800 template<typename Function, typename T1, typename T2>
0801 void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1),BOOST_THREAD_RV_REF(T2)), BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2)
0802 {
0803
0804
0805 detail::once_context ctx;
0806 while(::boost::detail::interlocked_read_acquire(&flag.status)
0807 !=ctx.function_complete_flag_value)
0808 {
0809 if(detail::enter_once_region(flag, ctx))
0810 {
0811 BOOST_TRY
0812 {
0813 f(
0814 thread_detail::decay_copy(boost::forward<T1>(p1)),
0815 thread_detail::decay_copy(boost::forward<T2>(p2))
0816 );
0817 }
0818 BOOST_CATCH(...)
0819 {
0820 detail::rollback_once_region(flag, ctx);
0821 BOOST_RETHROW
0822 }
0823 BOOST_CATCH_END
0824 detail::commit_once_region(flag, ctx);
0825 break;
0826 }
0827 if(!ctx.counted)
0828 {
0829 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0830 ctx.counted=true;
0831 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0832 if(status==ctx.function_complete_flag_value)
0833 {
0834 break;
0835 }
0836 if(!ctx.event_handle)
0837 {
0838 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0839 continue;
0840 }
0841 }
0842 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0843 ctx.event_handle,::boost::detail::win32::infinite,0));
0844 }
0845 }
0846 template<typename Function, typename T1, typename T2, typename T3>
0847 void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1),BOOST_THREAD_RV_REF(T2)), BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3)
0848 {
0849
0850
0851 detail::once_context ctx;
0852 while(::boost::detail::interlocked_read_acquire(&flag.status)
0853 !=ctx.function_complete_flag_value)
0854 {
0855 if(detail::enter_once_region(flag, ctx))
0856 {
0857 BOOST_TRY
0858 {
0859 f(
0860 thread_detail::decay_copy(boost::forward<T1>(p1)),
0861 thread_detail::decay_copy(boost::forward<T2>(p2)),
0862 thread_detail::decay_copy(boost::forward<T3>(p3))
0863 );
0864 }
0865 BOOST_CATCH(...)
0866 {
0867 detail::rollback_once_region(flag, ctx);
0868 BOOST_RETHROW
0869 }
0870 BOOST_CATCH_END
0871 detail::commit_once_region(flag, ctx);
0872 break;
0873 }
0874 if(!ctx.counted)
0875 {
0876 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0877 ctx.counted=true;
0878 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0879 if(status==ctx.function_complete_flag_value)
0880 {
0881 break;
0882 }
0883 if(!ctx.event_handle)
0884 {
0885 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0886 continue;
0887 }
0888 }
0889 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0890 ctx.event_handle,::boost::detail::win32::infinite,0));
0891 }
0892 }
0893 #endif
0894 template<typename Function>
0895 void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f)
0896 {
0897
0898
0899 detail::once_context ctx;
0900 while(::boost::detail::interlocked_read_acquire(&flag.status)
0901 !=ctx.function_complete_flag_value)
0902 {
0903 if(detail::enter_once_region(flag, ctx))
0904 {
0905 BOOST_TRY
0906 {
0907 f();
0908 }
0909 BOOST_CATCH(...)
0910 {
0911 detail::rollback_once_region(flag, ctx);
0912 BOOST_RETHROW
0913 }
0914 BOOST_CATCH_END
0915 detail::commit_once_region(flag, ctx);
0916 break;
0917 }
0918 if(!ctx.counted)
0919 {
0920 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0921 ctx.counted=true;
0922 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0923 if(status==ctx.function_complete_flag_value)
0924 {
0925 break;
0926 }
0927 if(!ctx.event_handle)
0928 {
0929 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0930 continue;
0931 }
0932 }
0933 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0934 ctx.event_handle,::boost::detail::win32::infinite,0));
0935 }
0936 }
0937
0938 template<typename Function, typename T1>
0939 void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1)
0940 {
0941
0942
0943 detail::once_context ctx;
0944 while(::boost::detail::interlocked_read_acquire(&flag.status)
0945 !=ctx.function_complete_flag_value)
0946 {
0947 if(detail::enter_once_region(flag, ctx))
0948 {
0949 BOOST_TRY
0950 {
0951 BOOST_THREAD_INVOKE_RET_VOID(
0952 thread_detail::decay_copy(boost::forward<Function>(f)),
0953 thread_detail::decay_copy(boost::forward<T1>(p1))
0954 ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
0955 }
0956 BOOST_CATCH(...)
0957 {
0958 detail::rollback_once_region(flag, ctx);
0959 BOOST_RETHROW
0960 }
0961 BOOST_CATCH_END
0962 detail::commit_once_region(flag, ctx);
0963 break;
0964 }
0965 if(!ctx.counted)
0966 {
0967 BOOST_INTERLOCKED_INCREMENT(&flag.count);
0968 ctx.counted=true;
0969 long status=::boost::detail::interlocked_read_acquire(&flag.status);
0970 if(status==ctx.function_complete_flag_value)
0971 {
0972 break;
0973 }
0974 if(!ctx.event_handle)
0975 {
0976 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
0977 continue;
0978 }
0979 }
0980 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
0981 ctx.event_handle,::boost::detail::win32::infinite,0));
0982 }
0983 }
0984 template<typename Function, typename T1, typename T2>
0985 void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2)
0986 {
0987
0988
0989 detail::once_context ctx;
0990 while(::boost::detail::interlocked_read_acquire(&flag.status)
0991 !=ctx.function_complete_flag_value)
0992 {
0993 if(detail::enter_once_region(flag, ctx))
0994 {
0995 BOOST_TRY
0996 {
0997 BOOST_THREAD_INVOKE_RET_VOID(
0998 thread_detail::decay_copy(boost::forward<Function>(f)),
0999 thread_detail::decay_copy(boost::forward<T1>(p1)),
1000 thread_detail::decay_copy(boost::forward<T2>(p2))
1001 ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
1002 }
1003 BOOST_CATCH(...)
1004 {
1005 detail::rollback_once_region(flag, ctx);
1006 BOOST_RETHROW
1007 }
1008 BOOST_CATCH_END
1009 detail::commit_once_region(flag, ctx);
1010 break;
1011 }
1012 if(!ctx.counted)
1013 {
1014 BOOST_INTERLOCKED_INCREMENT(&flag.count);
1015 ctx.counted=true;
1016 long status=::boost::detail::interlocked_read_acquire(&flag.status);
1017 if(status==ctx.function_complete_flag_value)
1018 {
1019 break;
1020 }
1021 if(!ctx.event_handle)
1022 {
1023 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
1024 continue;
1025 }
1026 }
1027 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
1028 ctx.event_handle,::boost::detail::win32::infinite,0));
1029 }
1030 }
1031 template<typename Function, typename T1, typename T2, typename T3>
1032 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)
1033 {
1034
1035
1036 detail::once_context ctx;
1037 while(::boost::detail::interlocked_read_acquire(&flag.status)
1038 !=ctx.function_complete_flag_value)
1039 {
1040 if(detail::enter_once_region(flag, ctx))
1041 {
1042 BOOST_TRY
1043 {
1044 BOOST_THREAD_INVOKE_RET_VOID(
1045 thread_detail::decay_copy(boost::forward<Function>(f)),
1046 thread_detail::decay_copy(boost::forward<T1>(p1)),
1047 thread_detail::decay_copy(boost::forward<T2>(p2)),
1048 thread_detail::decay_copy(boost::forward<T3>(p3))
1049 ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
1050
1051 }
1052 BOOST_CATCH(...)
1053 {
1054 detail::rollback_once_region(flag, ctx);
1055 BOOST_RETHROW
1056 }
1057 BOOST_CATCH_END
1058 detail::commit_once_region(flag, ctx);
1059 break;
1060 }
1061 if(!ctx.counted)
1062 {
1063 BOOST_INTERLOCKED_INCREMENT(&flag.count);
1064 ctx.counted=true;
1065 long status=::boost::detail::interlocked_read_acquire(&flag.status);
1066 if(status==ctx.function_complete_flag_value)
1067 {
1068 break;
1069 }
1070 if(!ctx.event_handle)
1071 {
1072 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
1073 continue;
1074 }
1075 }
1076 BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
1077 ctx.event_handle,::boost::detail::win32::infinite,0));
1078 }
1079 }
1080
1081 #endif
1082 #endif
1083 }
1084
1085 #include <boost/config/abi_suffix.hpp>
1086
1087 #endif