> From: Rob Stewart [mailto:stewart@sig.com]
> Sent: 07 August 2002 15:31
> From: Andrew J Bromage <ajb@spamcop.net>
> > class something
> > {
> > public:
> > const expensive_data&
> > get_expensive()
> > {
> > m_once.call_once(&make_expensive_data);
> > return *m_expensive;
> > }
> > something(const other_data& other)
> > : m_other(other)
> > {
> > }
> > private:
> > boost::once m_once;
> > std::auto_ptr<expensive_data> m_expensive;
> > other_data m_other;
> > void
> > make_expensive_data()
> > {
> > m_expensive = new expensive_data(m_other);
> > }
> > };
> >
> > Moreover (and this is what makes it tricky), I want to do it with as
> > little mutex contention as possible. In particular I want to avoid
> > obtaining a lock when get_expensive() is called after the expensive
> > data has been created.
>
> Is it that tricky? If there was a static pointer that was
> initialized to zero
> and was set to the address of the initialized object once
> ready, then a simple
> test of the pointer would indicate whether a synchronized
> check and possibly
> initialization is needed.
This is the double-checked locking pattern, which is not safe on some architectures --- the non-NULL-ness of the pointer may become visible before the pointed-to data, so it is no better than unchecked access to the data.
Anthony