summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/Boost/src/boost/thread/win32/once.hpp')
-rw-r--r--3rdParty/Boost/src/boost/thread/win32/once.hpp956
1 files changed, 908 insertions, 48 deletions
diff --git a/3rdParty/Boost/src/boost/thread/win32/once.hpp b/3rdParty/Boost/src/boost/thread/win32/once.hpp
index 3066b50..0ed56a5 100644
--- a/3rdParty/Boost/src/boost/thread/win32/once.hpp
+++ b/3rdParty/Boost/src/boost/thread/win32/once.hpp
@@ -5,7 +5,7 @@
//
// (C) Copyright 2005-7 Anthony Williams
// (C) Copyright 2005 John Maddock
-// (C) Copyright 2011-2012 Vicente J. Botet Escriba
+// (C) Copyright 2011-2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -18,6 +18,11 @@
#include <boost/detail/interlocked.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/detail/invoke.hpp>
+
+#include <boost/bind.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -31,6 +36,16 @@ namespace std
namespace boost
{
+ struct once_flag;
+ namespace detail
+ {
+ struct once_context;
+
+ inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT;
+ inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT;
+ inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT;
+ }
+
#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
struct once_flag
@@ -39,12 +54,12 @@ namespace boost
BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT
: status(0), count(0)
{}
- private:
long status;
long count;
- template<typename Function>
- friend
- void call_once(once_flag& flag,Function f);
+ private:
+ friend inline bool enter_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT;
+ friend inline void commit_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT;
+ friend inline void rollback_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT;
};
#define BOOST_ONCE_INIT once_flag()
@@ -59,6 +74,17 @@ namespace boost
#define BOOST_ONCE_INIT {0,0}
#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11
+#if defined BOOST_THREAD_PROVIDES_INVOKE
+#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke
+#define BOOST_THREAD_INVOKE_RET_VOID_CALL
+#elif defined BOOST_THREAD_PROVIDES_INVOKE_RET
+#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void>
+#define BOOST_THREAD_INVOKE_RET_VOID_CALL
+#else
+#define BOOST_THREAD_INVOKE_RET_VOID boost::bind
+#define BOOST_THREAD_INVOKE_RET_VOID_CALL ()
+#endif
+
namespace detail
{
#ifdef BOOST_NO_ANSI_APIS
@@ -135,94 +161,928 @@ namespace boost
::boost::detail::win32::event_initially_reset,
mutex_name);
}
- }
+ struct once_context {
+ long const function_complete_flag_value;
+ long const running_value;
+ bool counted;
+ detail::win32::handle_manager event_handle;
+ detail::once_char_type mutex_name[once_mutex_name_length];
+ once_context() :
+ function_complete_flag_value(0xc15730e2),
+ running_value(0x7f0725e3),
+ counted(false)
+ {
+ mutex_name[0]=0;
+ }
+ };
+ enum once_action {try_, break_, continue_};
+ inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
+ {
+ long status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,ctx.running_value,0);
+ if(!status)
+ {
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag);
+ }
+ if(ctx.event_handle)
+ {
+ ::boost::detail::win32::ResetEvent(ctx.event_handle);
+ }
+ return true;
+ }
+ return false;
+ }
+ inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
+ {
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ }
+ BOOST_INTERLOCKED_EXCHANGE(&flag.status,ctx.function_complete_flag_value);
+ if(!ctx.event_handle &&
+ (::boost::detail::interlocked_read_acquire(&flag.count)>1))
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ }
+ if(ctx.event_handle)
+ {
+ ::boost::detail::win32::SetEvent(ctx.event_handle);
+ }
+ }
+ inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
+ {
+ BOOST_INTERLOCKED_EXCHANGE(&flag.status,0);
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag);
+ }
+ if(ctx.event_handle)
+ {
+ ::boost::detail::win32::SetEvent(ctx.event_handle);
+ }
+ }
+ }
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+//#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
+ inline void call_once(once_flag& flag, void (*f)())
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ f();
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
+//#endif
+ template<typename Function>
+ inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ f();
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
+ template<typename Function, class A, class ...ArgTypes>
+ 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)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(
+ thread_detail::decay_copy(boost::forward<Function>(f)),
+ thread_detail::decay_copy(boost::forward<A>(a)),
+ thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
+ ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
+#else
+#if ! defined(BOOST_MSVC) && ! defined(BOOST_INTEL)
template<typename Function>
void call_once(once_flag& flag,Function f)
{
// Try for a quick win: if the procedure has already been called
// just skip through:
- long const function_complete_flag_value=0xc15730e2;
- long const running_value=0x7f0725e3;
- long status;
- bool counted=false;
- detail::win32::handle_manager event_handle;
- detail::once_char_type mutex_name[detail::once_mutex_name_length];
- mutex_name[0]=0;
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ f();
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
+ template<typename Function, typename T1>
+ void call_once(once_flag& flag,Function f, T1 p1)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
+ template<typename Function, typename T1, typename T2>
+ void call_once(once_flag& flag,Function f, T1 p1, T2 p2)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
+ template<typename Function, typename T1, typename T2, typename T3>
+ void call_once(once_flag& flag,Function f, T1 p1, T2 p2, T3 p3)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2,p3) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
+#elif defined BOOST_NO_CXX11_RVALUE_REFERENCES
- while((status=::boost::detail::interlocked_read_acquire(&flag.status))
- !=function_complete_flag_value)
+ template<typename Function>
+ void call_once(once_flag& flag,Function const&f)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
{
- status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,running_value,0);
- if(!status)
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ f();
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
{
-#ifndef BOOST_NO_EXCEPTIONS
- try // BOOST_NO_EXCEPTIONS protected
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
+ template<typename Function, typename T1>
+ void call_once(once_flag& flag,Function const&f, T1 const&p1)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
+ template<typename Function, typename T1, typename T2>
+ void call_once(once_flag& flag,Function const&f, T1 const&p1, T2 const&p2)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
+ template<typename Function, typename T1, typename T2, typename T3>
+ void call_once(once_flag& flag,Function const&f, T1 const&p1, T2 const&p2, T3 const&p3)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2,p3) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
#endif
+#if 1
+#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
+ inline void call_once(once_flag& flag, void (*f)())
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
{
- if(!event_handle)
+ BOOST_TRY
{
- event_handle=detail::open_once_event(mutex_name,&flag);
+ f();
}
- if(event_handle)
+ BOOST_CATCH(...)
{
- ::boost::detail::win32::ResetEvent(event_handle);
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
}
- f();
- if(!counted)
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
+ template<typename T1>
+ void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1)), BOOST_THREAD_RV_REF(T1) p1)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ f(
+ thread_detail::decay_copy(boost::forward<T1>(p1))
+ );
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
+ template<typename Function, typename T1, typename T2>
+ 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)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
{
- BOOST_INTERLOCKED_INCREMENT(&flag.count);
- counted=true;
+ f(
+ thread_detail::decay_copy(boost::forward<T1>(p1)),
+ thread_detail::decay_copy(boost::forward<T2>(p2))
+ );
}
- BOOST_INTERLOCKED_EXCHANGE(&flag.status,function_complete_flag_value);
- if(!event_handle &&
- (::boost::detail::interlocked_read_acquire(&flag.count)>1))
+ BOOST_CATCH(...)
{
- event_handle=detail::create_once_event(mutex_name,&flag);
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
}
- if(event_handle)
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
{
- ::boost::detail::win32::SetEvent(event_handle);
+ break;
}
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
+ template<typename Function, typename T1, typename T2, typename T3>
+ 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)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ f(
+ thread_detail::decay_copy(boost::forward<T1>(p1)),
+ thread_detail::decay_copy(boost::forward<T2>(p2)),
+ thread_detail::decay_copy(boost::forward<T3>(p3))
+ );
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
break;
}
-#ifndef BOOST_NO_EXCEPTIONS
- catch(...) // BOOST_NO_EXCEPTIONS protected
+ if(!ctx.counted)
{
- BOOST_INTERLOCKED_EXCHANGE(&flag.status,0);
- if(!event_handle)
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
{
- event_handle=detail::open_once_event(mutex_name,&flag);
+ break;
}
- if(event_handle)
+ if(!ctx.event_handle)
{
- ::boost::detail::win32::SetEvent(event_handle);
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
}
- throw; // BOOST_NO_EXCEPTIONS protected
}
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
#endif
+ template<typename Function>
+ void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ f();
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
}
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
- if(!counted)
+ template<typename Function, typename T1>
+ void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(
+ thread_detail::decay_copy(boost::forward<Function>(f)),
+ thread_detail::decay_copy(boost::forward<T1>(p1))
+ ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
{
BOOST_INTERLOCKED_INCREMENT(&flag.count);
- counted=true;
- status=::boost::detail::interlocked_read_acquire(&flag.status);
- if(status==function_complete_flag_value)
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
{
break;
}
- if(!event_handle)
+ if(!ctx.event_handle)
{
- event_handle=detail::create_once_event(mutex_name,&flag);
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
- event_handle,::boost::detail::win32::infinite));
+ ctx.event_handle,::boost::detail::win32::infinite));
}
}
+ template<typename Function, typename T1, typename T2>
+ void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(
+ thread_detail::decay_copy(boost::forward<Function>(f)),
+ thread_detail::decay_copy(boost::forward<T1>(p1)),
+ thread_detail::decay_copy(boost::forward<T2>(p2))
+ ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
+ template<typename Function, typename T1, typename T2, typename T3>
+ 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)
+ {
+ // Try for a quick win: if the procedure has already been called
+ // just skip through:
+ detail::once_context ctx;
+ while(::boost::detail::interlocked_read_acquire(&flag.status)
+ !=ctx.function_complete_flag_value)
+ {
+ if(detail::enter_once_region(flag, ctx))
+ {
+ BOOST_TRY
+ {
+ BOOST_THREAD_INVOKE_RET_VOID(
+ thread_detail::decay_copy(boost::forward<Function>(f)),
+ thread_detail::decay_copy(boost::forward<T1>(p1)),
+ thread_detail::decay_copy(boost::forward<T2>(p2)),
+ thread_detail::decay_copy(boost::forward<T3>(p3))
+ ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
+
+ }
+ BOOST_CATCH(...)
+ {
+ detail::rollback_once_region(flag, ctx);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ detail::commit_once_region(flag, ctx);
+ break;
+ }
+ if(!ctx.counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ ctx.counted=true;
+ long status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==ctx.function_complete_flag_value)
+ {
+ break;
+ }
+ if(!ctx.event_handle)
+ {
+ ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ ctx.event_handle,::boost::detail::win32::infinite));
+ }
+ }
+
+#endif
+#endif
}
#include <boost/config/abi_suffix.hpp>