> 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