diff --git a/hpx/hpx_fwd.hpp b/hpx/hpx_fwd.hpp index 690db6e721e6..092f39369ca9 100644 --- a/hpx/hpx_fwd.hpp +++ b/hpx/hpx_fwd.hpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include diff --git a/hpx/lcos/local/once.hpp b/hpx/lcos/local/once.hpp index 773114efe1b6..20e846a6d9f2 100644 --- a/hpx/lcos/local/once.hpp +++ b/hpx/lcos/local/once.hpp @@ -11,115 +11,30 @@ #define HPX_LCOS_LOCAL_ONCE_JAN_03_2013_0810PM #include - -#include -#include +#include +#include #include #include - -// #include -// #include -// #include -// #include +#include +#include namespace hpx { namespace lcos { namespace local { struct once_flag : boost::noncopyable { BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT - : status(0), count(0), event_(0) + : status_(0) {} private: - boost::atomic status; - boost::atomic count; - local::event event_; + boost::atomic status_; + lcos::local::event event_; template friend void call_once(once_flag& flag, Function f); }; -#define HPX_ONCE_INIT once_flag() - -// namespace detail -// { -// #ifdef BOOST_NO_ANSI_APIS -// typedef wchar_t once_char_type; -// #else -// typedef char once_char_type; -// #endif -// unsigned const once_mutex_name_fixed_length=54; -// unsigned const once_mutex_name_length=once_mutex_name_fixed_length+ -// sizeof(void*)*2+sizeof(unsigned long)*2+1; -// -// template -// void int_to_string(I p, once_char_type* buf) -// { -// for(unsigned i=0; i < sizeof(I)*2; ++i,++buf) -// { -// #ifdef BOOST_NO_ANSI_APIS -// once_char_type const a=L'A'; -// #else -// once_char_type const a='A'; -// #endif -// *buf = a + static_cast((p >> (i*4)) & 0x0f); -// } -// *buf = 0; -// } -// -// inline void name_once_mutex(once_char_type* mutex_name,void* flag_address) -// { -// #ifdef BOOST_NO_ANSI_APIS -// static const once_char_type fixed_mutex_name[]=L"Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag"; -// #else -// static const once_char_type fixed_mutex_name[]="Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag"; -// #endif -// BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) == -// (sizeof(once_char_type)*(once_mutex_name_fixed_length+1))); -// -// std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name)); -// detail::int_to_string(reinterpret_cast(flag_address), -// mutex_name + once_mutex_name_fixed_length); -// detail::int_to_string(win32::GetCurrentProcessId(), -// mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2); -// } -// -// inline void* open_once_event(once_char_type* mutex_name,void* flag_address) -// { -// if(!*mutex_name) -// { -// name_once_mutex(mutex_name,flag_address); -// } -// -// #ifdef BOOST_NO_ANSI_APIS -// return ::boost::detail::win32::OpenEventW( -// #else -// return ::boost::detail::win32::OpenEventA( -// #endif -// ::boost::detail::win32::synchronize | -// ::boost::detail::win32::event_modify_state, -// false, -// mutex_name); -// } -// -// inline void* create_once_event(once_char_type* mutex_name,void* flag_address) -// { -// if(!*mutex_name) -// { -// name_once_mutex(mutex_name,flag_address); -// } -// #ifdef BOOST_NO_ANSI_APIS -// return ::boost::detail::win32::CreateEventW( -// #else -// return ::boost::detail::win32::CreateEventA( -// #endif -// 0,::boost::detail::win32::manual_reset_event, -// ::boost::detail::win32::event_initially_reset, -// mutex_name); -// } -// } - /////////////////////////////////////////////////////////////////////////// template void call_once(once_flag& flag, Function f) @@ -128,84 +43,42 @@ namespace hpx { namespace lcos { namespace local // 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; - - while (flag.status.load(boost::memory_order_acquire) != + while (flag.status_.load(boost::memory_order_acquire) != function_complete_flag_value) { - status = 0; - if (flag.status.compare_exchange_strong(status, running_value)) + long status = 0; + if (flag.status_.compare_exchange_strong(status, running_value)) { try { - if (!event_handle) - { - event_handle=detail::open_once_event(mutex_name,&flag); - } - if(event_handle) - { - ::boost::detail::win32::ResetEvent(event_handle); - } + // reset event to ensure its usability in case the + // wrapped function was throwing an exception before + flag.event_.reset(); f(); - if (!counted) - { - ++flag.count; - counted.store(true); - } - BOOST_INTERLOCKED_EXCHANGE(&flag.status,function_complete_flag_value); - if(!event_handle && - (::boost::detail::interlocked_read_acquire(&flag.count)>1)) - { - event_handle=detail::create_once_event(mutex_name,&flag); - } - if(event_handle) - { - ::boost::detail::win32::SetEvent(event_handle); - } + // set status to done, release waiting threads + flag.status_.store(function_complete_flag_value); + flag.event_.set(); break; } catch (...) { - flag.status.exchange(0); - if(!event_handle) - { - event_handle=detail::open_once_event(mutex_name,&flag); - } - if(event_handle) - { - ::boost::detail::win32::SetEvent(event_handle); - } - BOOST_RETHROW - } - BOOST_CATCH_END - } + // reset status to initial, release waiting threads + flag.status_.store(0); + flag.event_.set(); - if(!counted) - { - BOOST_INTERLOCKED_INCREMENT(&flag.count); - counted=true; - status=::boost::detail::interlocked_read_acquire(&flag.status); - if(status==function_complete_flag_value) - { - break; - } - if(!event_handle) - { - event_handle=detail::create_once_event(mutex_name,&flag); - continue; + throw; } } - BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( - event_handle,::boost::detail::win32::infinite)); + + // we're done if function was called + if (status == function_complete_flag_value) + break; + + // wait for the function finish executing + flag.event_.wait(); } } -} - -#include +}}} #endif diff --git a/hpx/lcos/local/once_fwd.hpp b/hpx/lcos/local/once_fwd.hpp new file mode 100644 index 000000000000..66195f04ee7a --- /dev/null +++ b/hpx/lcos/local/once_fwd.hpp @@ -0,0 +1,18 @@ +// Copyright (c) 2013 Hartmut Kaiser +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(HPX_LCOS_LOCAL_ONCE_FWD_JAN_05_2013_0427PM) +#define HPX_LCOS_LOCAL_ONCE_FWD_JAN_05_2013_0427PM + +namespace hpx { namespace lcos { namespace local +{ + // call_once support + struct once_flag; +}}} + +#define HPX_ONCE_INIT hpx::lcos::local::once_flag() + +#endif +