Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/thread/win32/once.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 #ifndef BOOST_THREAD_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/detail/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 | |
30 namespace std | |
31 { | |
32 using ::memcpy; | |
33 using ::ptrdiff_t; | |
34 } | |
35 #endif | |
36 | |
37 namespace 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 #ifdef BOOST_NO_ANSI_APIS | |
156 return ::boost::detail::win32::CreateEventW( | |
157 #else | |
158 return ::boost::detail::win32::CreateEventA( | |
159 #endif | |
160 0,::boost::detail::win32::manual_reset_event, | |
161 ::boost::detail::win32::event_initially_reset, | |
162 mutex_name); | |
163 } | |
164 | |
165 struct once_context { | |
166 long const function_complete_flag_value; | |
167 long const running_value; | |
168 bool counted; | |
169 detail::win32::handle_manager event_handle; | |
170 detail::once_char_type mutex_name[once_mutex_name_length]; | |
171 once_context() : | |
172 function_complete_flag_value(0xc15730e2), | |
173 running_value(0x7f0725e3), | |
174 counted(false) | |
175 { | |
176 mutex_name[0]=0; | |
177 } | |
178 }; | |
179 enum once_action {try_, break_, continue_}; | |
180 | |
181 inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT | |
182 { | |
183 long status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,ctx.running_value,0); | |
184 if(!status) | |
185 { | |
186 if(!ctx.event_handle) | |
187 { | |
188 ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag); | |
189 } | |
190 if(ctx.event_handle) | |
191 { | |
192 ::boost::detail::win32::ResetEvent(ctx.event_handle); | |
193 } | |
194 return true; | |
195 } | |
196 return false; | |
197 } | |
198 inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT | |
199 { | |
200 if(!ctx.counted) | |
201 { | |
202 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
203 ctx.counted=true; | |
204 } | |
205 BOOST_INTERLOCKED_EXCHANGE(&flag.status,ctx.function_complete_flag_value); | |
206 if(!ctx.event_handle && | |
207 (::boost::detail::interlocked_read_acquire(&flag.count)>1)) | |
208 { | |
209 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
210 } | |
211 if(ctx.event_handle) | |
212 { | |
213 ::boost::detail::win32::SetEvent(ctx.event_handle); | |
214 } | |
215 } | |
216 inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT | |
217 { | |
218 BOOST_INTERLOCKED_EXCHANGE(&flag.status,0); | |
219 if(!ctx.event_handle) | |
220 { | |
221 ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag); | |
222 } | |
223 if(ctx.event_handle) | |
224 { | |
225 ::boost::detail::win32::SetEvent(ctx.event_handle); | |
226 } | |
227 } | |
228 } | |
229 | |
230 #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES | |
231 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) | |
232 inline void call_once(once_flag& flag, void (*f)()) | |
233 { | |
234 // Try for a quick win: if the procedure has already been called | |
235 // just skip through: | |
236 detail::once_context ctx; | |
237 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
238 !=ctx.function_complete_flag_value) | |
239 { | |
240 if(detail::enter_once_region(flag, ctx)) | |
241 { | |
242 BOOST_TRY | |
243 { | |
244 f(); | |
245 } | |
246 BOOST_CATCH(...) | |
247 { | |
248 detail::rollback_once_region(flag, ctx); | |
249 BOOST_RETHROW | |
250 } | |
251 BOOST_CATCH_END | |
252 detail::commit_once_region(flag, ctx); | |
253 break; | |
254 } | |
255 if(!ctx.counted) | |
256 { | |
257 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
258 ctx.counted=true; | |
259 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
260 if(status==ctx.function_complete_flag_value) | |
261 { | |
262 break; | |
263 } | |
264 if(!ctx.event_handle) | |
265 { | |
266 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
267 continue; | |
268 } | |
269 } | |
270 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
271 ctx.event_handle,::boost::detail::win32::infinite)); | |
272 } | |
273 } | |
274 //#endif | |
275 template<typename Function> | |
276 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f) | |
277 { | |
278 // Try for a quick win: if the procedure has already been called | |
279 // just skip through: | |
280 detail::once_context ctx; | |
281 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
282 !=ctx.function_complete_flag_value) | |
283 { | |
284 if(detail::enter_once_region(flag, ctx)) | |
285 { | |
286 BOOST_TRY | |
287 { | |
288 f(); | |
289 } | |
290 BOOST_CATCH(...) | |
291 { | |
292 detail::rollback_once_region(flag, ctx); | |
293 BOOST_RETHROW | |
294 } | |
295 BOOST_CATCH_END | |
296 detail::commit_once_region(flag, ctx); | |
297 break; | |
298 } | |
299 if(!ctx.counted) | |
300 { | |
301 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
302 ctx.counted=true; | |
303 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
304 if(status==ctx.function_complete_flag_value) | |
305 { | |
306 break; | |
307 } | |
308 if(!ctx.event_handle) | |
309 { | |
310 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
311 continue; | |
312 } | |
313 } | |
314 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
315 ctx.event_handle,::boost::detail::win32::infinite)); | |
316 } | |
317 } | |
318 template<typename Function, class A, class ...ArgTypes> | |
319 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) | |
320 { | |
321 // Try for a quick win: if the procedure has already been called | |
322 // just skip through: | |
323 detail::once_context ctx; | |
324 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
325 !=ctx.function_complete_flag_value) | |
326 { | |
327 if(detail::enter_once_region(flag, ctx)) | |
328 { | |
329 BOOST_TRY | |
330 { | |
331 BOOST_THREAD_INVOKE_RET_VOID( | |
332 thread_detail::decay_copy(boost::forward<Function>(f)), | |
333 thread_detail::decay_copy(boost::forward<A>(a)), | |
334 thread_detail::decay_copy(boost::forward<ArgTypes>(args))... | |
335 ) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
336 } | |
337 BOOST_CATCH(...) | |
338 { | |
339 detail::rollback_once_region(flag, ctx); | |
340 BOOST_RETHROW | |
341 } | |
342 BOOST_CATCH_END | |
343 detail::commit_once_region(flag, ctx); | |
344 break; | |
345 } | |
346 if(!ctx.counted) | |
347 { | |
348 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
349 ctx.counted=true; | |
350 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
351 if(status==ctx.function_complete_flag_value) | |
352 { | |
353 break; | |
354 } | |
355 if(!ctx.event_handle) | |
356 { | |
357 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
358 continue; | |
359 } | |
360 } | |
361 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
362 ctx.event_handle,::boost::detail::win32::infinite)); | |
363 } | |
364 } | |
365 #else | |
366 #if ! defined(BOOST_MSVC) && ! defined(BOOST_INTEL) | |
367 template<typename Function> | |
368 void call_once(once_flag& flag,Function f) | |
369 { | |
370 // Try for a quick win: if the procedure has already been called | |
371 // just skip through: | |
372 detail::once_context ctx; | |
373 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
374 !=ctx.function_complete_flag_value) | |
375 { | |
376 if(detail::enter_once_region(flag, ctx)) | |
377 { | |
378 BOOST_TRY | |
379 { | |
380 f(); | |
381 } | |
382 BOOST_CATCH(...) | |
383 { | |
384 detail::rollback_once_region(flag, ctx); | |
385 BOOST_RETHROW | |
386 } | |
387 BOOST_CATCH_END | |
388 detail::commit_once_region(flag, ctx); | |
389 break; | |
390 } | |
391 if(!ctx.counted) | |
392 { | |
393 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
394 ctx.counted=true; | |
395 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
396 if(status==ctx.function_complete_flag_value) | |
397 { | |
398 break; | |
399 } | |
400 if(!ctx.event_handle) | |
401 { | |
402 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
403 continue; | |
404 } | |
405 } | |
406 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
407 ctx.event_handle,::boost::detail::win32::infinite)); | |
408 } | |
409 } | |
410 template<typename Function, typename T1> | |
411 void call_once(once_flag& flag,Function f, T1 p1) | |
412 { | |
413 // Try for a quick win: if the procedure has already been called | |
414 // just skip through: | |
415 detail::once_context ctx; | |
416 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
417 !=ctx.function_complete_flag_value) | |
418 { | |
419 if(detail::enter_once_region(flag, ctx)) | |
420 { | |
421 BOOST_TRY | |
422 { | |
423 BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
424 } | |
425 BOOST_CATCH(...) | |
426 { | |
427 detail::rollback_once_region(flag, ctx); | |
428 BOOST_RETHROW | |
429 } | |
430 BOOST_CATCH_END | |
431 detail::commit_once_region(flag, ctx); | |
432 break; | |
433 } | |
434 if(!ctx.counted) | |
435 { | |
436 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
437 ctx.counted=true; | |
438 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
439 if(status==ctx.function_complete_flag_value) | |
440 { | |
441 break; | |
442 } | |
443 if(!ctx.event_handle) | |
444 { | |
445 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
446 continue; | |
447 } | |
448 } | |
449 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
450 ctx.event_handle,::boost::detail::win32::infinite)); | |
451 } | |
452 } | |
453 template<typename Function, typename T1, typename T2> | |
454 void call_once(once_flag& flag,Function f, T1 p1, T2 p2) | |
455 { | |
456 // Try for a quick win: if the procedure has already been called | |
457 // just skip through: | |
458 detail::once_context ctx; | |
459 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
460 !=ctx.function_complete_flag_value) | |
461 { | |
462 if(detail::enter_once_region(flag, ctx)) | |
463 { | |
464 BOOST_TRY | |
465 { | |
466 BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
467 } | |
468 BOOST_CATCH(...) | |
469 { | |
470 detail::rollback_once_region(flag, ctx); | |
471 BOOST_RETHROW | |
472 } | |
473 BOOST_CATCH_END | |
474 detail::commit_once_region(flag, ctx); | |
475 break; | |
476 } | |
477 if(!ctx.counted) | |
478 { | |
479 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
480 ctx.counted=true; | |
481 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
482 if(status==ctx.function_complete_flag_value) | |
483 { | |
484 break; | |
485 } | |
486 if(!ctx.event_handle) | |
487 { | |
488 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
489 continue; | |
490 } | |
491 } | |
492 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
493 ctx.event_handle,::boost::detail::win32::infinite)); | |
494 } | |
495 } | |
496 template<typename Function, typename T1, typename T2, typename T3> | |
497 void call_once(once_flag& flag,Function f, T1 p1, T2 p2, T3 p3) | |
498 { | |
499 // Try for a quick win: if the procedure has already been called | |
500 // just skip through: | |
501 detail::once_context ctx; | |
502 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
503 !=ctx.function_complete_flag_value) | |
504 { | |
505 if(detail::enter_once_region(flag, ctx)) | |
506 { | |
507 BOOST_TRY | |
508 { | |
509 BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2,p3) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
510 } | |
511 BOOST_CATCH(...) | |
512 { | |
513 detail::rollback_once_region(flag, ctx); | |
514 BOOST_RETHROW | |
515 } | |
516 BOOST_CATCH_END | |
517 detail::commit_once_region(flag, ctx); | |
518 break; | |
519 } | |
520 if(!ctx.counted) | |
521 { | |
522 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
523 ctx.counted=true; | |
524 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
525 if(status==ctx.function_complete_flag_value) | |
526 { | |
527 break; | |
528 } | |
529 if(!ctx.event_handle) | |
530 { | |
531 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
532 continue; | |
533 } | |
534 } | |
535 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
536 ctx.event_handle,::boost::detail::win32::infinite)); | |
537 } | |
538 } | |
539 #elif defined BOOST_NO_CXX11_RVALUE_REFERENCES | |
540 | |
541 template<typename Function> | |
542 void call_once(once_flag& flag,Function const&f) | |
543 { | |
544 // Try for a quick win: if the procedure has already been called | |
545 // just skip through: | |
546 detail::once_context ctx; | |
547 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
548 !=ctx.function_complete_flag_value) | |
549 { | |
550 if(detail::enter_once_region(flag, ctx)) | |
551 { | |
552 BOOST_TRY | |
553 { | |
554 f(); | |
555 } | |
556 BOOST_CATCH(...) | |
557 { | |
558 detail::rollback_once_region(flag, ctx); | |
559 BOOST_RETHROW | |
560 } | |
561 BOOST_CATCH_END | |
562 detail::commit_once_region(flag, ctx); | |
563 break; | |
564 } | |
565 if(!ctx.counted) | |
566 { | |
567 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
568 ctx.counted=true; | |
569 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
570 if(status==ctx.function_complete_flag_value) | |
571 { | |
572 break; | |
573 } | |
574 if(!ctx.event_handle) | |
575 { | |
576 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
577 continue; | |
578 } | |
579 } | |
580 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
581 ctx.event_handle,::boost::detail::win32::infinite)); | |
582 } | |
583 } | |
584 template<typename Function, typename T1> | |
585 void call_once(once_flag& flag,Function const&f, T1 const&p1) | |
586 { | |
587 // Try for a quick win: if the procedure has already been called | |
588 // just skip through: | |
589 detail::once_context ctx; | |
590 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
591 !=ctx.function_complete_flag_value) | |
592 { | |
593 if(detail::enter_once_region(flag, ctx)) | |
594 { | |
595 BOOST_TRY | |
596 { | |
597 BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
598 } | |
599 BOOST_CATCH(...) | |
600 { | |
601 detail::rollback_once_region(flag, ctx); | |
602 BOOST_RETHROW | |
603 } | |
604 BOOST_CATCH_END | |
605 detail::commit_once_region(flag, ctx); | |
606 break; | |
607 } | |
608 if(!ctx.counted) | |
609 { | |
610 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
611 ctx.counted=true; | |
612 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
613 if(status==ctx.function_complete_flag_value) | |
614 { | |
615 break; | |
616 } | |
617 if(!ctx.event_handle) | |
618 { | |
619 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
620 continue; | |
621 } | |
622 } | |
623 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
624 ctx.event_handle,::boost::detail::win32::infinite)); | |
625 } | |
626 } | |
627 template<typename Function, typename T1, typename T2> | |
628 void call_once(once_flag& flag,Function const&f, T1 const&p1, T2 const&p2) | |
629 { | |
630 // Try for a quick win: if the procedure has already been called | |
631 // just skip through: | |
632 detail::once_context ctx; | |
633 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
634 !=ctx.function_complete_flag_value) | |
635 { | |
636 if(detail::enter_once_region(flag, ctx)) | |
637 { | |
638 BOOST_TRY | |
639 { | |
640 BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
641 } | |
642 BOOST_CATCH(...) | |
643 { | |
644 detail::rollback_once_region(flag, ctx); | |
645 BOOST_RETHROW | |
646 } | |
647 BOOST_CATCH_END | |
648 detail::commit_once_region(flag, ctx); | |
649 break; | |
650 } | |
651 if(!ctx.counted) | |
652 { | |
653 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
654 ctx.counted=true; | |
655 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
656 if(status==ctx.function_complete_flag_value) | |
657 { | |
658 break; | |
659 } | |
660 if(!ctx.event_handle) | |
661 { | |
662 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
663 continue; | |
664 } | |
665 } | |
666 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
667 ctx.event_handle,::boost::detail::win32::infinite)); | |
668 } | |
669 } | |
670 template<typename Function, typename T1, typename T2, typename T3> | |
671 void call_once(once_flag& flag,Function const&f, T1 const&p1, T2 const&p2, T3 const&p3) | |
672 { | |
673 // Try for a quick win: if the procedure has already been called | |
674 // just skip through: | |
675 detail::once_context ctx; | |
676 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
677 !=ctx.function_complete_flag_value) | |
678 { | |
679 if(detail::enter_once_region(flag, ctx)) | |
680 { | |
681 BOOST_TRY | |
682 { | |
683 BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2,p3) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
684 } | |
685 BOOST_CATCH(...) | |
686 { | |
687 detail::rollback_once_region(flag, ctx); | |
688 BOOST_RETHROW | |
689 } | |
690 BOOST_CATCH_END | |
691 detail::commit_once_region(flag, ctx); | |
692 break; | |
693 } | |
694 if(!ctx.counted) | |
695 { | |
696 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
697 ctx.counted=true; | |
698 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
699 if(status==ctx.function_complete_flag_value) | |
700 { | |
701 break; | |
702 } | |
703 if(!ctx.event_handle) | |
704 { | |
705 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
706 continue; | |
707 } | |
708 } | |
709 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
710 ctx.event_handle,::boost::detail::win32::infinite)); | |
711 } | |
712 } | |
713 #endif | |
714 #if 1 | |
715 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) | |
716 inline void call_once(once_flag& flag, void (*f)()) | |
717 { | |
718 // Try for a quick win: if the procedure has already been called | |
719 // just skip through: | |
720 detail::once_context ctx; | |
721 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
722 !=ctx.function_complete_flag_value) | |
723 { | |
724 if(detail::enter_once_region(flag, ctx)) | |
725 { | |
726 BOOST_TRY | |
727 { | |
728 f(); | |
729 } | |
730 BOOST_CATCH(...) | |
731 { | |
732 detail::rollback_once_region(flag, ctx); | |
733 BOOST_RETHROW | |
734 } | |
735 BOOST_CATCH_END | |
736 detail::commit_once_region(flag, ctx); | |
737 break; | |
738 } | |
739 if(!ctx.counted) | |
740 { | |
741 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
742 ctx.counted=true; | |
743 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
744 if(status==ctx.function_complete_flag_value) | |
745 { | |
746 break; | |
747 } | |
748 if(!ctx.event_handle) | |
749 { | |
750 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
751 continue; | |
752 } | |
753 } | |
754 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
755 ctx.event_handle,::boost::detail::win32::infinite)); | |
756 } | |
757 } | |
758 template<typename T1> | |
759 void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1)), BOOST_THREAD_RV_REF(T1) p1) | |
760 { | |
761 // Try for a quick win: if the procedure has already been called | |
762 // just skip through: | |
763 detail::once_context ctx; | |
764 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
765 !=ctx.function_complete_flag_value) | |
766 { | |
767 if(detail::enter_once_region(flag, ctx)) | |
768 { | |
769 BOOST_TRY | |
770 { | |
771 f( | |
772 thread_detail::decay_copy(boost::forward<T1>(p1)) | |
773 ); | |
774 } | |
775 BOOST_CATCH(...) | |
776 { | |
777 detail::rollback_once_region(flag, ctx); | |
778 BOOST_RETHROW | |
779 } | |
780 BOOST_CATCH_END | |
781 detail::commit_once_region(flag, ctx); | |
782 break; | |
783 } | |
784 if(!ctx.counted) | |
785 { | |
786 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
787 ctx.counted=true; | |
788 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
789 if(status==ctx.function_complete_flag_value) | |
790 { | |
791 break; | |
792 } | |
793 if(!ctx.event_handle) | |
794 { | |
795 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
796 continue; | |
797 } | |
798 } | |
799 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
800 ctx.event_handle,::boost::detail::win32::infinite)); | |
801 } | |
802 } | |
803 template<typename Function, typename T1, typename T2> | |
804 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) | |
805 { | |
806 // Try for a quick win: if the procedure has already been called | |
807 // just skip through: | |
808 detail::once_context ctx; | |
809 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
810 !=ctx.function_complete_flag_value) | |
811 { | |
812 if(detail::enter_once_region(flag, ctx)) | |
813 { | |
814 BOOST_TRY | |
815 { | |
816 f( | |
817 thread_detail::decay_copy(boost::forward<T1>(p1)), | |
818 thread_detail::decay_copy(boost::forward<T2>(p2)) | |
819 ); | |
820 } | |
821 BOOST_CATCH(...) | |
822 { | |
823 detail::rollback_once_region(flag, ctx); | |
824 BOOST_RETHROW | |
825 } | |
826 BOOST_CATCH_END | |
827 detail::commit_once_region(flag, ctx); | |
828 break; | |
829 } | |
830 if(!ctx.counted) | |
831 { | |
832 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
833 ctx.counted=true; | |
834 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
835 if(status==ctx.function_complete_flag_value) | |
836 { | |
837 break; | |
838 } | |
839 if(!ctx.event_handle) | |
840 { | |
841 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
842 continue; | |
843 } | |
844 } | |
845 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
846 ctx.event_handle,::boost::detail::win32::infinite)); | |
847 } | |
848 } | |
849 template<typename Function, typename T1, typename T2, typename T3> | |
850 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) | |
851 { | |
852 // Try for a quick win: if the procedure has already been called | |
853 // just skip through: | |
854 detail::once_context ctx; | |
855 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
856 !=ctx.function_complete_flag_value) | |
857 { | |
858 if(detail::enter_once_region(flag, ctx)) | |
859 { | |
860 BOOST_TRY | |
861 { | |
862 f( | |
863 thread_detail::decay_copy(boost::forward<T1>(p1)), | |
864 thread_detail::decay_copy(boost::forward<T2>(p2)), | |
865 thread_detail::decay_copy(boost::forward<T3>(p3)) | |
866 ); | |
867 } | |
868 BOOST_CATCH(...) | |
869 { | |
870 detail::rollback_once_region(flag, ctx); | |
871 BOOST_RETHROW | |
872 } | |
873 BOOST_CATCH_END | |
874 detail::commit_once_region(flag, ctx); | |
875 break; | |
876 } | |
877 if(!ctx.counted) | |
878 { | |
879 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
880 ctx.counted=true; | |
881 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
882 if(status==ctx.function_complete_flag_value) | |
883 { | |
884 break; | |
885 } | |
886 if(!ctx.event_handle) | |
887 { | |
888 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
889 continue; | |
890 } | |
891 } | |
892 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
893 ctx.event_handle,::boost::detail::win32::infinite)); | |
894 } | |
895 } | |
896 #endif | |
897 template<typename Function> | |
898 void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f) | |
899 { | |
900 // Try for a quick win: if the procedure has already been called | |
901 // just skip through: | |
902 detail::once_context ctx; | |
903 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
904 !=ctx.function_complete_flag_value) | |
905 { | |
906 if(detail::enter_once_region(flag, ctx)) | |
907 { | |
908 BOOST_TRY | |
909 { | |
910 f(); | |
911 } | |
912 BOOST_CATCH(...) | |
913 { | |
914 detail::rollback_once_region(flag, ctx); | |
915 BOOST_RETHROW | |
916 } | |
917 BOOST_CATCH_END | |
918 detail::commit_once_region(flag, ctx); | |
919 break; | |
920 } | |
921 if(!ctx.counted) | |
922 { | |
923 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
924 ctx.counted=true; | |
925 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
926 if(status==ctx.function_complete_flag_value) | |
927 { | |
928 break; | |
929 } | |
930 if(!ctx.event_handle) | |
931 { | |
932 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
933 continue; | |
934 } | |
935 } | |
936 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
937 ctx.event_handle,::boost::detail::win32::infinite)); | |
938 } | |
939 } | |
940 | |
941 template<typename Function, typename T1> | |
942 void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1) | |
943 { | |
944 // Try for a quick win: if the procedure has already been called | |
945 // just skip through: | |
946 detail::once_context ctx; | |
947 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
948 !=ctx.function_complete_flag_value) | |
949 { | |
950 if(detail::enter_once_region(flag, ctx)) | |
951 { | |
952 BOOST_TRY | |
953 { | |
954 BOOST_THREAD_INVOKE_RET_VOID( | |
955 thread_detail::decay_copy(boost::forward<Function>(f)), | |
956 thread_detail::decay_copy(boost::forward<T1>(p1)) | |
957 ) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
958 } | |
959 BOOST_CATCH(...) | |
960 { | |
961 detail::rollback_once_region(flag, ctx); | |
962 BOOST_RETHROW | |
963 } | |
964 BOOST_CATCH_END | |
965 detail::commit_once_region(flag, ctx); | |
966 break; | |
967 } | |
968 if(!ctx.counted) | |
969 { | |
970 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
971 ctx.counted=true; | |
972 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
973 if(status==ctx.function_complete_flag_value) | |
974 { | |
975 break; | |
976 } | |
977 if(!ctx.event_handle) | |
978 { | |
979 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
980 continue; | |
981 } | |
982 } | |
983 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
984 ctx.event_handle,::boost::detail::win32::infinite)); | |
985 } | |
986 } | |
987 template<typename Function, typename T1, typename T2> | |
988 void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2) | |
989 { | |
990 // Try for a quick win: if the procedure has already been called | |
991 // just skip through: | |
992 detail::once_context ctx; | |
993 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
994 !=ctx.function_complete_flag_value) | |
995 { | |
996 if(detail::enter_once_region(flag, ctx)) | |
997 { | |
998 BOOST_TRY | |
999 { | |
1000 BOOST_THREAD_INVOKE_RET_VOID( | |
1001 thread_detail::decay_copy(boost::forward<Function>(f)), | |
1002 thread_detail::decay_copy(boost::forward<T1>(p1)), | |
1003 thread_detail::decay_copy(boost::forward<T2>(p2)) | |
1004 ) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
1005 } | |
1006 BOOST_CATCH(...) | |
1007 { | |
1008 detail::rollback_once_region(flag, ctx); | |
1009 BOOST_RETHROW | |
1010 } | |
1011 BOOST_CATCH_END | |
1012 detail::commit_once_region(flag, ctx); | |
1013 break; | |
1014 } | |
1015 if(!ctx.counted) | |
1016 { | |
1017 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
1018 ctx.counted=true; | |
1019 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
1020 if(status==ctx.function_complete_flag_value) | |
1021 { | |
1022 break; | |
1023 } | |
1024 if(!ctx.event_handle) | |
1025 { | |
1026 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
1027 continue; | |
1028 } | |
1029 } | |
1030 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
1031 ctx.event_handle,::boost::detail::win32::infinite)); | |
1032 } | |
1033 } | |
1034 template<typename Function, typename T1, typename T2, typename T3> | |
1035 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) | |
1036 { | |
1037 // Try for a quick win: if the procedure has already been called | |
1038 // just skip through: | |
1039 detail::once_context ctx; | |
1040 while(::boost::detail::interlocked_read_acquire(&flag.status) | |
1041 !=ctx.function_complete_flag_value) | |
1042 { | |
1043 if(detail::enter_once_region(flag, ctx)) | |
1044 { | |
1045 BOOST_TRY | |
1046 { | |
1047 BOOST_THREAD_INVOKE_RET_VOID( | |
1048 thread_detail::decay_copy(boost::forward<Function>(f)), | |
1049 thread_detail::decay_copy(boost::forward<T1>(p1)), | |
1050 thread_detail::decay_copy(boost::forward<T2>(p2)), | |
1051 thread_detail::decay_copy(boost::forward<T3>(p3)) | |
1052 ) BOOST_THREAD_INVOKE_RET_VOID_CALL; | |
1053 | |
1054 } | |
1055 BOOST_CATCH(...) | |
1056 { | |
1057 detail::rollback_once_region(flag, ctx); | |
1058 BOOST_RETHROW | |
1059 } | |
1060 BOOST_CATCH_END | |
1061 detail::commit_once_region(flag, ctx); | |
1062 break; | |
1063 } | |
1064 if(!ctx.counted) | |
1065 { | |
1066 BOOST_INTERLOCKED_INCREMENT(&flag.count); | |
1067 ctx.counted=true; | |
1068 long status=::boost::detail::interlocked_read_acquire(&flag.status); | |
1069 if(status==ctx.function_complete_flag_value) | |
1070 { | |
1071 break; | |
1072 } | |
1073 if(!ctx.event_handle) | |
1074 { | |
1075 ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); | |
1076 continue; | |
1077 } | |
1078 } | |
1079 BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( | |
1080 ctx.event_handle,::boost::detail::win32::infinite)); | |
1081 } | |
1082 } | |
1083 | |
1084 #endif | |
1085 #endif | |
1086 } | |
1087 | |
1088 #include <boost/config/abi_suffix.hpp> | |
1089 | |
1090 #endif |