
Anthony Williams wrote:
"Peter Dimov" <pdimov@mmltd.net> writes:
I don't see call_once in jss_thread.zip, by the way; maybe you forgot to put it into the archive?
Oops. Thanks for spotting that. I've added it to the archive, and updated it to take multiple arguments in passing.
Some comments on that: template<typename Function> void call_once(once_flag& flag,Function f) { // Try for a quick win: if the proceedure has already been called // just skip through: long const function_complete_flag_value=0xc15730e2; if(::jss::detail::interlocked_read(&flag)!=function_complete_flag_value) { char mutex_name[::jss::detail::once_mutex_name_length]; void* const mutex_handle(::jss::detail::create_once_mutex(mutex_name,&flag)); BOOST_ASSERT(mutex_handle); detail::win32::handle_holder const closer(mutex_handle); detail::win32_mutex_scoped_lock const lock(mutex_handle); if(::jss::detail::interlocked_read(&flag)!=function_complete_flag_value) { f(); JSS_INTERLOCKED_EXCHANGE(&flag,function_complete_flag_value); } } } The first load needs to be a load_acquire; the second can be ordinary since it's done under a lock. The store needs to be store_release. An interlocked_read is stronger ('ordered') and more expensive than needed on a hardware level, but is 'relaxed' on a compiler level under MSVC 7.1 (the optimizer moves code around it). It's 'ordered' for the compiler as well under 8.0; the intrinsics have been changed to be compiler barriers as well. InterlockedExchange is similar. A load_acquire can be implemented as a volatile read under 8.0, and a volatile read followed by _ReadWriteBarrier under 7.1.