]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/thread/include/boost/thread/win32/once.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / thread / include / boost / thread / win32 / once.hpp
CommitLineData
7c673cae
FG
1#ifndef BOOST_THREAD_WIN32_ONCE_HPP
2#define BOOST_THREAD_WIN32_ONCE_HPP
3
4// once.hpp
5//
6// (C) Copyright 2005-7 Anthony Williams
7// (C) Copyright 2005 John Maddock
8// (C) Copyright 2011-2013 Vicente J. Botet Escriba
9//
10// Distributed under the Boost Software License, Version 1.0. (See
11// accompanying file LICENSE_1_0.txt or copy at
12// http://www.boost.org/LICENSE_1_0.txt)
13
14#include <cstring>
15#include <cstddef>
16#include <boost/assert.hpp>
17#include <boost/static_assert.hpp>
18#include <boost/detail/interlocked.hpp>
19#include <boost/thread/win32/thread_primitives.hpp>
20#include <boost/thread/win32/interlocked_read.hpp>
21#include <boost/core/no_exceptions_support.hpp>
22#include <boost/thread/detail/move.hpp>
23#include <boost/thread/detail/invoke.hpp>
24
25#include <boost/bind.hpp>
26
27#include <boost/config/abi_prefix.hpp>
28
29#ifdef BOOST_NO_STDC_NAMESPACE
30namespace std
31{
32 using ::memcpy;
33 using ::ptrdiff_t;
34}
35#endif
36
37namespace boost
38{
39 struct once_flag;
40 namespace detail
41 {
42 struct once_context;
43
44 inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT;
45 inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT;
46 inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT;
47 }
48
49#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
50
51 struct once_flag
52 {
53 BOOST_THREAD_NO_COPYABLE(once_flag)
54 BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT
55 : status(0), count(0)
56 {}
57 long status;
58 long count;
59 private:
60 friend inline bool enter_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT;
61 friend inline void commit_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT;
62 friend inline void rollback_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT;
63 };
64
65#define BOOST_ONCE_INIT once_flag()
66#else // BOOST_THREAD_PROVIDES_ONCE_CXX11
67
68 struct once_flag
69 {
70 long status;
71 long count;
72 };
73
74#define BOOST_ONCE_INIT {0,0}
75#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11
76
77#if defined BOOST_THREAD_PROVIDES_INVOKE
78#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke
79#define BOOST_THREAD_INVOKE_RET_VOID_CALL
80#elif defined BOOST_THREAD_PROVIDES_INVOKE_RET
81#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void>
82#define BOOST_THREAD_INVOKE_RET_VOID_CALL
83#else
84#define BOOST_THREAD_INVOKE_RET_VOID boost::bind
85#define BOOST_THREAD_INVOKE_RET_VOID_CALL ()
86#endif
87
88 namespace detail
89 {
90#ifdef BOOST_NO_ANSI_APIS
91 typedef wchar_t once_char_type;
92#else
93 typedef char once_char_type;
94#endif
95 unsigned const once_mutex_name_fixed_length=54;
96 unsigned const once_mutex_name_length=once_mutex_name_fixed_length+
97 sizeof(void*)*2+sizeof(unsigned long)*2+1;
98
99 template <class I>
100 void int_to_string(I p, once_char_type* buf)
101 {
102 for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
103 {
104#ifdef BOOST_NO_ANSI_APIS
105 once_char_type const a=L'A';
106#else
107 once_char_type const a='A';
108#endif
109 *buf = a + static_cast<once_char_type>((p >> (i*4)) & 0x0f);
110 }
111 *buf = 0;
112 }
113
114 inline void name_once_mutex(once_char_type* mutex_name,void* flag_address)
115 {
116#ifdef BOOST_NO_ANSI_APIS
117 static const once_char_type fixed_mutex_name[]=L"Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
118#else
119 static const once_char_type fixed_mutex_name[]="Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
120#endif
121 BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) ==
122 (sizeof(once_char_type)*(once_mutex_name_fixed_length+1)));
123
124 std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name));
125 detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address),
126 mutex_name + once_mutex_name_fixed_length);
127 detail::int_to_string(win32::GetCurrentProcessId(),
128 mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2);
129 }
130
131 inline void* open_once_event(once_char_type* mutex_name,void* flag_address)
132 {
133 if(!*mutex_name)
134 {
135 name_once_mutex(mutex_name,flag_address);
136 }
137
138#ifdef BOOST_NO_ANSI_APIS
139 return ::boost::detail::win32::OpenEventW(
140#else
141 return ::boost::detail::win32::OpenEventA(
142#endif
143 ::boost::detail::win32::synchronize |
144 ::boost::detail::win32::event_modify_state,
145 false,
146 mutex_name);
147 }
148
149 inline void* create_once_event(once_char_type* mutex_name,void* flag_address)
150 {
151 if(!*mutex_name)
152 {
153 name_once_mutex(mutex_name,flag_address);
154 }
155
156 return ::boost::detail::win32::create_event(
157 mutex_name,
158 ::boost::detail::win32::manual_reset_event,
159 ::boost::detail::win32::event_initially_reset);
160 }
161
162 struct once_context {
163 long const function_complete_flag_value;
164 long const running_value;
165 bool counted;
166 detail::win32::handle_manager event_handle;
167 detail::once_char_type mutex_name[once_mutex_name_length];
168 once_context() :
169 function_complete_flag_value(0xc15730e2),
170 running_value(0x7f0725e3),
171 counted(false)
172 {
173 mutex_name[0]=0;
174 }
175 };
176 enum once_action {try_, break_, continue_};
177
178 inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
179 {
180 long status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,ctx.running_value,0);
181 if(!status)
182 {
183 if(!ctx.event_handle)
184 {
185 ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag);
186 }
187 if(ctx.event_handle)
188 {
189 ::boost::detail::win32::ResetEvent(ctx.event_handle);
190 }
191 return true;
192 }
193 return false;
194 }
195 inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
196 {
197 if(!ctx.counted)
198 {
199 BOOST_INTERLOCKED_INCREMENT(&flag.count);
200 ctx.counted=true;
201 }
202 BOOST_INTERLOCKED_EXCHANGE(&flag.status,ctx.function_complete_flag_value);
203 if(!ctx.event_handle &&
204 (::boost::detail::interlocked_read_acquire(&flag.count)>1))
205 {
206 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
207 }
208 if(ctx.event_handle)
209 {
210 ::boost::detail::win32::SetEvent(ctx.event_handle);
211 }
212 }
213 inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
214 {
215 BOOST_INTERLOCKED_EXCHANGE(&flag.status,0);
216 if(!ctx.event_handle)
217 {
218 ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag);
219 }
220 if(ctx.event_handle)
221 {
222 ::boost::detail::win32::SetEvent(ctx.event_handle);
223 }
224 }
225 }
226
227#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
228//#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
229 inline void call_once(once_flag& flag, void (*f)())
230 {
231 // Try for a quick win: if the procedure has already been called
232 // just skip through:
233 detail::once_context ctx;
234 while(::boost::detail::interlocked_read_acquire(&flag.status)
235 !=ctx.function_complete_flag_value)
236 {
237 if(detail::enter_once_region(flag, ctx))
238 {
239 BOOST_TRY
240 {
241 f();
242 }
243 BOOST_CATCH(...)
244 {
245 detail::rollback_once_region(flag, ctx);
246 BOOST_RETHROW
247 }
248 BOOST_CATCH_END
249 detail::commit_once_region(flag, ctx);
250 break;
251 }
252 if(!ctx.counted)
253 {
254 BOOST_INTERLOCKED_INCREMENT(&flag.count);
255 ctx.counted=true;
256 long status=::boost::detail::interlocked_read_acquire(&flag.status);
257 if(status==ctx.function_complete_flag_value)
258 {
259 break;
260 }
261 if(!ctx.event_handle)
262 {
263 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
264 continue;
265 }
266 }
267 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
268 ctx.event_handle,::boost::detail::win32::infinite, 0));
269 }
270 }
271//#endif
272 template<typename Function>
273 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f)
274 {
275 // Try for a quick win: if the procedure has already been called
276 // just skip through:
277 detail::once_context ctx;
278 while(::boost::detail::interlocked_read_acquire(&flag.status)
279 !=ctx.function_complete_flag_value)
280 {
281 if(detail::enter_once_region(flag, ctx))
282 {
283 BOOST_TRY
284 {
285 f();
286 }
287 BOOST_CATCH(...)
288 {
289 detail::rollback_once_region(flag, ctx);
290 BOOST_RETHROW
291 }
292 BOOST_CATCH_END
293 detail::commit_once_region(flag, ctx);
294 break;
295 }
296 if(!ctx.counted)
297 {
298 BOOST_INTERLOCKED_INCREMENT(&flag.count);
299 ctx.counted=true;
300 long status=::boost::detail::interlocked_read_acquire(&flag.status);
301 if(status==ctx.function_complete_flag_value)
302 {
303 break;
304 }
305 if(!ctx.event_handle)
306 {
307 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
308 continue;
309 }
310 }
311 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
312 ctx.event_handle,::boost::detail::win32::infinite,0));
313 }
314 }
315 template<typename Function, class A, class ...ArgTypes>
316 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)
317 {
318 // Try for a quick win: if the procedure has already been called
319 // just skip through:
320 detail::once_context ctx;
321 while(::boost::detail::interlocked_read_acquire(&flag.status)
322 !=ctx.function_complete_flag_value)
323 {
324 if(detail::enter_once_region(flag, ctx))
325 {
326 BOOST_TRY
327 {
328 BOOST_THREAD_INVOKE_RET_VOID(
329 thread_detail::decay_copy(boost::forward<Function>(f)),
330 thread_detail::decay_copy(boost::forward<A>(a)),
331 thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
332 ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
333 }
334 BOOST_CATCH(...)
335 {
336 detail::rollback_once_region(flag, ctx);
337 BOOST_RETHROW
338 }
339 BOOST_CATCH_END
340 detail::commit_once_region(flag, ctx);
341 break;
342 }
343 if(!ctx.counted)
344 {
345 BOOST_INTERLOCKED_INCREMENT(&flag.count);
346 ctx.counted=true;
347 long status=::boost::detail::interlocked_read_acquire(&flag.status);
348 if(status==ctx.function_complete_flag_value)
349 {
350 break;
351 }
352 if(!ctx.event_handle)
353 {
354 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
355 continue;
356 }
357 }
358 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
359 ctx.event_handle,::boost::detail::win32::infinite,0));
360 }
361 }
362#else
363#if ! defined(BOOST_MSVC) && ! defined(BOOST_INTEL)
364 template<typename Function>
365 void call_once(once_flag& flag,Function f)
366 {
367 // Try for a quick win: if the procedure has already been called
368 // just skip through:
369 detail::once_context ctx;
370 while(::boost::detail::interlocked_read_acquire(&flag.status)
371 !=ctx.function_complete_flag_value)
372 {
373 if(detail::enter_once_region(flag, ctx))
374 {
375 BOOST_TRY
376 {
377 f();
378 }
379 BOOST_CATCH(...)
380 {
381 detail::rollback_once_region(flag, ctx);
382 BOOST_RETHROW
383 }
384 BOOST_CATCH_END
385 detail::commit_once_region(flag, ctx);
386 break;
387 }
388 if(!ctx.counted)
389 {
390 BOOST_INTERLOCKED_INCREMENT(&flag.count);
391 ctx.counted=true;
392 long status=::boost::detail::interlocked_read_acquire(&flag.status);
393 if(status==ctx.function_complete_flag_value)
394 {
395 break;
396 }
397 if(!ctx.event_handle)
398 {
399 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
400 continue;
401 }
402 }
403 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
404 ctx.event_handle,::boost::detail::win32::infinite,0));
405 }
406 }
407 template<typename Function, typename T1>
408 void call_once(once_flag& flag,Function f, T1 p1)
409 {
410 // Try for a quick win: if the procedure has already been called
411 // just skip through:
412 detail::once_context ctx;
413 while(::boost::detail::interlocked_read_acquire(&flag.status)
414 !=ctx.function_complete_flag_value)
415 {
416 if(detail::enter_once_region(flag, ctx))
417 {
418 BOOST_TRY
419 {
420 BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL;
421 }
422 BOOST_CATCH(...)
423 {
424 detail::rollback_once_region(flag, ctx);
425 BOOST_RETHROW
426 }
427 BOOST_CATCH_END
428 detail::commit_once_region(flag, ctx);
429 break;
430 }
431 if(!ctx.counted)
432 {
433 BOOST_INTERLOCKED_INCREMENT(&flag.count);
434 ctx.counted=true;
435 long status=::boost::detail::interlocked_read_acquire(&flag.status);
436 if(status==ctx.function_complete_flag_value)
437 {
438 break;
439 }
440 if(!ctx.event_handle)
441 {
442 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
443 continue;
444 }
445 }
446 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
447 ctx.event_handle,::boost::detail::win32::infinite,0));
448 }
449 }
450 template<typename Function, typename T1, typename T2>
451 void call_once(once_flag& flag,Function f, T1 p1, T2 p2)
452 {
453 // Try for a quick win: if the procedure has already been called
454 // just skip through:
455 detail::once_context ctx;
456 while(::boost::detail::interlocked_read_acquire(&flag.status)
457 !=ctx.function_complete_flag_value)
458 {
459 if(detail::enter_once_region(flag, ctx))
460 {
461 BOOST_TRY
462 {
463 BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2) BOOST_THREAD_INVOKE_RET_VOID_CALL;
464 }
465 BOOST_CATCH(...)
466 {
467 detail::rollback_once_region(flag, ctx);
468 BOOST_RETHROW
469 }
470 BOOST_CATCH_END
471 detail::commit_once_region(flag, ctx);
472 break;
473 }
474 if(!ctx.counted)
475 {
476 BOOST_INTERLOCKED_INCREMENT(&flag.count);
477 ctx.counted=true;
478 long status=::boost::detail::interlocked_read_acquire(&flag.status);
479 if(status==ctx.function_complete_flag_value)
480 {
481 break;
482 }
483 if(!ctx.event_handle)
484 {
485 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
486 continue;
487 }
488 }
489 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
490 ctx.event_handle,::boost::detail::win32::infinite,0));
491 }
492 }
493 template<typename Function, typename T1, typename T2, typename T3>
494 void call_once(once_flag& flag,Function f, T1 p1, T2 p2, T3 p3)
495 {
496 // Try for a quick win: if the procedure has already been called
497 // just skip through:
498 detail::once_context ctx;
499 while(::boost::detail::interlocked_read_acquire(&flag.status)
500 !=ctx.function_complete_flag_value)
501 {
502 if(detail::enter_once_region(flag, ctx))
503 {
504 BOOST_TRY
505 {
506 BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2,p3) BOOST_THREAD_INVOKE_RET_VOID_CALL;
507 }
508 BOOST_CATCH(...)
509 {
510 detail::rollback_once_region(flag, ctx);
511 BOOST_RETHROW
512 }
513 BOOST_CATCH_END
514 detail::commit_once_region(flag, ctx);
515 break;
516 }
517 if(!ctx.counted)
518 {
519 BOOST_INTERLOCKED_INCREMENT(&flag.count);
520 ctx.counted=true;
521 long status=::boost::detail::interlocked_read_acquire(&flag.status);
522 if(status==ctx.function_complete_flag_value)
523 {
524 break;
525 }
526 if(!ctx.event_handle)
527 {
528 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
529 continue;
530 }
531 }
532 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
533 ctx.event_handle,::boost::detail::win32::infinite,0));
534 }
535 }
536#elif defined BOOST_NO_CXX11_RVALUE_REFERENCES
537
538 template<typename Function>
539 void call_once(once_flag& flag,Function const&f)
540 {
541 // Try for a quick win: if the procedure has already been called
542 // just skip through:
543 detail::once_context ctx;
544 while(::boost::detail::interlocked_read_acquire(&flag.status)
545 !=ctx.function_complete_flag_value)
546 {
547 if(detail::enter_once_region(flag, ctx))
548 {
549 BOOST_TRY
550 {
551 f();
552 }
553 BOOST_CATCH(...)
554 {
555 detail::rollback_once_region(flag, ctx);
556 BOOST_RETHROW
557 }
558 BOOST_CATCH_END
559 detail::commit_once_region(flag, ctx);
560 break;
561 }
562 if(!ctx.counted)
563 {
564 BOOST_INTERLOCKED_INCREMENT(&flag.count);
565 ctx.counted=true;
566 long status=::boost::detail::interlocked_read_acquire(&flag.status);
567 if(status==ctx.function_complete_flag_value)
568 {
569 break;
570 }
571 if(!ctx.event_handle)
572 {
573 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
574 continue;
575 }
576 }
577 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
578 ctx.event_handle,::boost::detail::win32::infinite,0));
579 }
580 }
581 template<typename Function, typename T1>
582 void call_once(once_flag& flag,Function const&f, T1 const&p1)
583 {
584 // Try for a quick win: if the procedure has already been called
585 // just skip through:
586 detail::once_context ctx;
587 while(::boost::detail::interlocked_read_acquire(&flag.status)
588 !=ctx.function_complete_flag_value)
589 {
590 if(detail::enter_once_region(flag, ctx))
591 {
592 BOOST_TRY
593 {
594 BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL;
595 }
596 BOOST_CATCH(...)
597 {
598 detail::rollback_once_region(flag, ctx);
599 BOOST_RETHROW
600 }
601 BOOST_CATCH_END
602 detail::commit_once_region(flag, ctx);
603 break;
604 }
605 if(!ctx.counted)
606 {
607 BOOST_INTERLOCKED_INCREMENT(&flag.count);
608 ctx.counted=true;
609 long status=::boost::detail::interlocked_read_acquire(&flag.status);
610 if(status==ctx.function_complete_flag_value)
611 {
612 break;
613 }
614 if(!ctx.event_handle)
615 {
616 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
617 continue;
618 }
619 }
620 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
621 ctx.event_handle,::boost::detail::win32::infinite,0));
622 }
623 }
624 template<typename Function, typename T1, typename T2>
625 void call_once(once_flag& flag,Function const&f, T1 const&p1, T2 const&p2)
626 {
627 // Try for a quick win: if the procedure has already been called
628 // just skip through:
629 detail::once_context ctx;
630 while(::boost::detail::interlocked_read_acquire(&flag.status)
631 !=ctx.function_complete_flag_value)
632 {
633 if(detail::enter_once_region(flag, ctx))
634 {
635 BOOST_TRY
636 {
637 BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2) BOOST_THREAD_INVOKE_RET_VOID_CALL;
638 }
639 BOOST_CATCH(...)
640 {
641 detail::rollback_once_region(flag, ctx);
642 BOOST_RETHROW
643 }
644 BOOST_CATCH_END
645 detail::commit_once_region(flag, ctx);
646 break;
647 }
648 if(!ctx.counted)
649 {
650 BOOST_INTERLOCKED_INCREMENT(&flag.count);
651 ctx.counted=true;
652 long status=::boost::detail::interlocked_read_acquire(&flag.status);
653 if(status==ctx.function_complete_flag_value)
654 {
655 break;
656 }
657 if(!ctx.event_handle)
658 {
659 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
660 continue;
661 }
662 }
663 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
664 ctx.event_handle,::boost::detail::win32::infinite,0));
665 }
666 }
667 template<typename Function, typename T1, typename T2, typename T3>
668 void call_once(once_flag& flag,Function const&f, T1 const&p1, T2 const&p2, T3 const&p3)
669 {
670 // Try for a quick win: if the procedure has already been called
671 // just skip through:
672 detail::once_context ctx;
673 while(::boost::detail::interlocked_read_acquire(&flag.status)
674 !=ctx.function_complete_flag_value)
675 {
676 if(detail::enter_once_region(flag, ctx))
677 {
678 BOOST_TRY
679 {
680 BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2,p3) BOOST_THREAD_INVOKE_RET_VOID_CALL;
681 }
682 BOOST_CATCH(...)
683 {
684 detail::rollback_once_region(flag, ctx);
685 BOOST_RETHROW
686 }
687 BOOST_CATCH_END
688 detail::commit_once_region(flag, ctx);
689 break;
690 }
691 if(!ctx.counted)
692 {
693 BOOST_INTERLOCKED_INCREMENT(&flag.count);
694 ctx.counted=true;
695 long status=::boost::detail::interlocked_read_acquire(&flag.status);
696 if(status==ctx.function_complete_flag_value)
697 {
698 break;
699 }
700 if(!ctx.event_handle)
701 {
702 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
703 continue;
704 }
705 }
706 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
707 ctx.event_handle,::boost::detail::win32::infinite,0));
708 }
709 }
710#endif
711#if 1
712#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
713 inline void call_once(once_flag& flag, void (*f)())
714 {
715 // Try for a quick win: if the procedure has already been called
716 // just skip through:
717 detail::once_context ctx;
718 while(::boost::detail::interlocked_read_acquire(&flag.status)
719 !=ctx.function_complete_flag_value)
720 {
721 if(detail::enter_once_region(flag, ctx))
722 {
723 BOOST_TRY
724 {
725 f();
726 }
727 BOOST_CATCH(...)
728 {
729 detail::rollback_once_region(flag, ctx);
730 BOOST_RETHROW
731 }
732 BOOST_CATCH_END
733 detail::commit_once_region(flag, ctx);
734 break;
735 }
736 if(!ctx.counted)
737 {
738 BOOST_INTERLOCKED_INCREMENT(&flag.count);
739 ctx.counted=true;
740 long status=::boost::detail::interlocked_read_acquire(&flag.status);
741 if(status==ctx.function_complete_flag_value)
742 {
743 break;
744 }
745 if(!ctx.event_handle)
746 {
747 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
748 continue;
749 }
750 }
751 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
752 ctx.event_handle,::boost::detail::win32::infinite,0));
753 }
754 }
755 template<typename T1>
756 void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1)), BOOST_THREAD_RV_REF(T1) p1)
757 {
758 // Try for a quick win: if the procedure has already been called
759 // just skip through:
760 detail::once_context ctx;
761 while(::boost::detail::interlocked_read_acquire(&flag.status)
762 !=ctx.function_complete_flag_value)
763 {
764 if(detail::enter_once_region(flag, ctx))
765 {
766 BOOST_TRY
767 {
768 f(
769 thread_detail::decay_copy(boost::forward<T1>(p1))
770 );
771 }
772 BOOST_CATCH(...)
773 {
774 detail::rollback_once_region(flag, ctx);
775 BOOST_RETHROW
776 }
777 BOOST_CATCH_END
778 detail::commit_once_region(flag, ctx);
779 break;
780 }
781 if(!ctx.counted)
782 {
783 BOOST_INTERLOCKED_INCREMENT(&flag.count);
784 ctx.counted=true;
785 long status=::boost::detail::interlocked_read_acquire(&flag.status);
786 if(status==ctx.function_complete_flag_value)
787 {
788 break;
789 }
790 if(!ctx.event_handle)
791 {
792 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
793 continue;
794 }
795 }
796 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
797 ctx.event_handle,::boost::detail::win32::infinite,0));
798 }
799 }
800 template<typename Function, typename T1, typename T2>
801 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)
802 {
803 // Try for a quick win: if the procedure has already been called
804 // just skip through:
805 detail::once_context ctx;
806 while(::boost::detail::interlocked_read_acquire(&flag.status)
807 !=ctx.function_complete_flag_value)
808 {
809 if(detail::enter_once_region(flag, ctx))
810 {
811 BOOST_TRY
812 {
813 f(
814 thread_detail::decay_copy(boost::forward<T1>(p1)),
815 thread_detail::decay_copy(boost::forward<T2>(p2))
816 );
817 }
818 BOOST_CATCH(...)
819 {
820 detail::rollback_once_region(flag, ctx);
821 BOOST_RETHROW
822 }
823 BOOST_CATCH_END
824 detail::commit_once_region(flag, ctx);
825 break;
826 }
827 if(!ctx.counted)
828 {
829 BOOST_INTERLOCKED_INCREMENT(&flag.count);
830 ctx.counted=true;
831 long status=::boost::detail::interlocked_read_acquire(&flag.status);
832 if(status==ctx.function_complete_flag_value)
833 {
834 break;
835 }
836 if(!ctx.event_handle)
837 {
838 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
839 continue;
840 }
841 }
842 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
843 ctx.event_handle,::boost::detail::win32::infinite,0));
844 }
845 }
846 template<typename Function, typename T1, typename T2, typename T3>
847 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)
848 {
849 // Try for a quick win: if the procedure has already been called
850 // just skip through:
851 detail::once_context ctx;
852 while(::boost::detail::interlocked_read_acquire(&flag.status)
853 !=ctx.function_complete_flag_value)
854 {
855 if(detail::enter_once_region(flag, ctx))
856 {
857 BOOST_TRY
858 {
859 f(
860 thread_detail::decay_copy(boost::forward<T1>(p1)),
861 thread_detail::decay_copy(boost::forward<T2>(p2)),
862 thread_detail::decay_copy(boost::forward<T3>(p3))
863 );
864 }
865 BOOST_CATCH(...)
866 {
867 detail::rollback_once_region(flag, ctx);
868 BOOST_RETHROW
869 }
870 BOOST_CATCH_END
871 detail::commit_once_region(flag, ctx);
872 break;
873 }
874 if(!ctx.counted)
875 {
876 BOOST_INTERLOCKED_INCREMENT(&flag.count);
877 ctx.counted=true;
878 long status=::boost::detail::interlocked_read_acquire(&flag.status);
879 if(status==ctx.function_complete_flag_value)
880 {
881 break;
882 }
883 if(!ctx.event_handle)
884 {
885 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
886 continue;
887 }
888 }
889 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
890 ctx.event_handle,::boost::detail::win32::infinite,0));
891 }
892 }
893#endif
894 template<typename Function>
895 void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f)
896 {
897 // Try for a quick win: if the procedure has already been called
898 // just skip through:
899 detail::once_context ctx;
900 while(::boost::detail::interlocked_read_acquire(&flag.status)
901 !=ctx.function_complete_flag_value)
902 {
903 if(detail::enter_once_region(flag, ctx))
904 {
905 BOOST_TRY
906 {
907 f();
908 }
909 BOOST_CATCH(...)
910 {
911 detail::rollback_once_region(flag, ctx);
912 BOOST_RETHROW
913 }
914 BOOST_CATCH_END
915 detail::commit_once_region(flag, ctx);
916 break;
917 }
918 if(!ctx.counted)
919 {
920 BOOST_INTERLOCKED_INCREMENT(&flag.count);
921 ctx.counted=true;
922 long status=::boost::detail::interlocked_read_acquire(&flag.status);
923 if(status==ctx.function_complete_flag_value)
924 {
925 break;
926 }
927 if(!ctx.event_handle)
928 {
929 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
930 continue;
931 }
932 }
933 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
934 ctx.event_handle,::boost::detail::win32::infinite,0));
935 }
936 }
937
938 template<typename Function, typename T1>
939 void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1)
940 {
941 // Try for a quick win: if the procedure has already been called
942 // just skip through:
943 detail::once_context ctx;
944 while(::boost::detail::interlocked_read_acquire(&flag.status)
945 !=ctx.function_complete_flag_value)
946 {
947 if(detail::enter_once_region(flag, ctx))
948 {
949 BOOST_TRY
950 {
951 BOOST_THREAD_INVOKE_RET_VOID(
952 thread_detail::decay_copy(boost::forward<Function>(f)),
953 thread_detail::decay_copy(boost::forward<T1>(p1))
954 ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
955 }
956 BOOST_CATCH(...)
957 {
958 detail::rollback_once_region(flag, ctx);
959 BOOST_RETHROW
960 }
961 BOOST_CATCH_END
962 detail::commit_once_region(flag, ctx);
963 break;
964 }
965 if(!ctx.counted)
966 {
967 BOOST_INTERLOCKED_INCREMENT(&flag.count);
968 ctx.counted=true;
969 long status=::boost::detail::interlocked_read_acquire(&flag.status);
970 if(status==ctx.function_complete_flag_value)
971 {
972 break;
973 }
974 if(!ctx.event_handle)
975 {
976 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
977 continue;
978 }
979 }
980 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
981 ctx.event_handle,::boost::detail::win32::infinite,0));
982 }
983 }
984 template<typename Function, typename T1, typename T2>
985 void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2)
986 {
987 // Try for a quick win: if the procedure has already been called
988 // just skip through:
989 detail::once_context ctx;
990 while(::boost::detail::interlocked_read_acquire(&flag.status)
991 !=ctx.function_complete_flag_value)
992 {
993 if(detail::enter_once_region(flag, ctx))
994 {
995 BOOST_TRY
996 {
997 BOOST_THREAD_INVOKE_RET_VOID(
998 thread_detail::decay_copy(boost::forward<Function>(f)),
999 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::detail::win32::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 // Try for a quick win: if the procedure has already been called
1035 // just skip through:
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::detail::win32::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