Back to home page

EIC code displayed by LXR

 
 

    


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 //  once.hpp
0005 //
0006 //  (C) Copyright 2005-7 Anthony Williams
0007 //  (C) Copyright 2005 John Maddock
0008 //  (C) Copyright 2011-2013 Vicente J. Botet Escriba
0009 //
0010 //  Distributed under the Boost Software License, Version 1.0. (See
0011 //  accompanying file LICENSE_1_0.txt or copy at
0012 //  http://www.boost.org/LICENSE_1_0.txt)
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 // BOOST_THREAD_PROVIDES_ONCE_CXX11
0067 
0068     struct once_flag
0069     {
0070         long status;
0071         long count;
0072     };
0073 
0074 #define BOOST_ONCE_INIT {0,0}
0075 #endif  // BOOST_THREAD_PROVIDES_ONCE_CXX11
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 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
0229     inline void call_once(once_flag& flag, void (*f)())
0230     {
0231         // Try for a quick win: if the procedure has already been called
0232         // just skip through:
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 //#endif
0272     template<typename Function>
0273     inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f)
0274     {
0275         // Try for a quick win: if the procedure has already been called
0276         // just skip through:
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         // Try for a quick win: if the procedure has already been called
0319         // just skip through:
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         // Try for a quick win: if the procedure has already been called
0368         // just skip through:
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         // Try for a quick win: if the procedure has already been called
0411         // just skip through:
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         // Try for a quick win: if the procedure has already been called
0454         // just skip through:
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         // Try for a quick win: if the procedure has already been called
0497         // just skip through:
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         // Try for a quick win: if the procedure has already been called
0542         // just skip through:
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         // Try for a quick win: if the procedure has already been called
0585         // just skip through:
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         // Try for a quick win: if the procedure has already been called
0628         // just skip through:
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         // Try for a quick win: if the procedure has already been called
0671         // just skip through:
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             // Try for a quick win: if the procedure has already been called
0716             // just skip through:
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             // Try for a quick win: if the procedure has already been called
0759             // just skip through:
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             // Try for a quick win: if the procedure has already been called
0804             // just skip through:
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             // Try for a quick win: if the procedure has already been called
0850             // just skip through:
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         // Try for a quick win: if the procedure has already been called
0898         // just skip through:
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         // Try for a quick win: if the procedure has already been called
0942         // just skip through:
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         // Try for a quick win: if the procedure has already been called
0988         // just skip through:
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         // 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::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