|
Boost : |
From: Peter Dimov (pdimov_at_[hidden])
Date: 2007-03-22 20:33:06
Anthony Williams wrote:
> "Peter Dimov" <pdimov_at_[hidden]> 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.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk