Boost logo

Boost :

Subject: Re: [boost] [Boost.utility]
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2010-01-26 14:01:10


----- Original Message -----
From: "Andrew Chinkoff" <achinkoff_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Tuesday, January 26, 2010 7:07 PM
Subject: Re: [boost] [Boost.utility]

>
>
> Thread-safe (instance_ == NULL) comparison:
>
> static T& Instance()
> {
> /**
> Perform the Double-Check pattern.
> See http://www.research.ibm.com/designpatterns/pubs/ph-jun96.txt.
> */
> if (instance_ == NULL)
> {
> boost::mutex::scoped_lock locker(mtx_instance_);
> if (instance_ == NULL)
> {
> instance_ = new T();
> destroyer_.set_doomed(instance_);
> }
> }
> return *instance_;
> }

The paper you point (http://www.research.ibm.com/designpatterns/pubs/ph-jun96.txt.) presumes at least that:

static T& Instance()
{
 /**
   Perform the Double-Check pattern.
   See
  */
 if ( ATOMIC(instance_ == NULL))
 {
  boost::mutex::scoped_lock locker(mtx_instance_);
  if (ATOMIC(instance_ == NULL))
  {
   T* tmp = new T()); (1)
   ATOMIC(instance_ = tmp); (2)
   destroyer_.set_doomed(instance_);
  }
 }
 return *instance_;
}

Where (2) must be executed after (1).

It is a known issue that these operations are not always atomic (as they depend on the architecture and even on the optimization options). So to be portable you will need to define instance_ as atomic<T*>.

In this case call instance() each time will be more expensive calling it once, store it in a smart pointer and then get this pointer from the stack.

the use could be something like

class S : singleton<T> {...};

S::smart_ptr ptr;

use ptr to access the single instance of S.

To get the same performances without the smart pointer you will need the following

S* ptr=S::instance();

Best,
Vicente


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk