|
Boost : |
From: Andrew J Bromage (ajb_at_[hidden])
Date: 2002-08-07 18:07:56
G'day all.
On Wed, Aug 07, 2002 at 11:19:40AM -0400, Jason Stewart wrote:
> I saw a technique in C/C++ User Journal, August 2000 by Pete Becker that
> had a good solution. Basically, you check the pointer if it is not null
> then the expensive_data has been initialized. If it is null then you grab
> the mutex and check it again. This second check allows you to make sure
> that someone else did not beat you too the initialization.
As others have noted, this isn't guaranteed to work due to cache
coherency problems.
On some architectures we have an atomic_count operation which would
avoid the lock:
class something
{
public:
something()
: m_atomic_count(0)
{
}
const expensive_data& get_expensive()
{
if (!(long)m_atomic_count)
{
boost::Lock lock(m_mutex);
if (!(long)m_atomic_count)
{
make_expensive_data;i()
m_atomic_count++;
}
}
return *m_expensive;
}
private:
boost::mutex m_mutex
boost::detail::atomic_count m_atomic_count;
std::auto_ptr<expensive_data> m_expensive;
};
On others we don't, or it's simulated with a mutex, in which case
a flag protected by a mutex is going to be cheaper. In yet other
architectures we may, in fact, have access to a memory barrier
operation, which would also solve the problem.
Given that the "best" way to do it varies so widely, it seems that
this might be a good candidate for abstraction.
Cheers,
Andrew Bromage
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk