thread-safe singleton? 
Author Message
 thread-safe singleton?

Anyone have a good, simple thread-safe technique for forcing classes to only
allow a single instantiation?


Mon, 18 Jul 2005 23:00:10 GMT  
 thread-safe singleton?


Fri, 19 Jun 1992 00:00:00 GMT  
 thread-safe singleton?


Should be this:

...
private:
    // Critical section.
    static CriticalSection m_instanceCs;
...

with:

CriticalSection MyClass::m_instanceCs;

in a CPP file somewhere.

Jay



Tue, 19 Jul 2005 00:59:31 GMT  
 thread-safe singleton?


Fri, 19 Jun 1992 00:00:00 GMT  
 thread-safe singleton?


Quote:
> Anyone have a good, simple thread-safe technique for forcing classes to
only
> allow a single instantiation?

// Off the top (not compiled)...
class CriticalSection
{
public:
    CriticalSection() { InitializeCriticalSection(&m_cs); }
    ~CriticalSection() { DeleteCriticalSection(&m_cs); }
    void Enter(void) { EnterCriticalSection(&m_cs); }
    void Leave(void) { LeaveCriticalSection(&m_cs);

    // Nested class.
    class Locker
    {
     public:
        Locker(CriticalSection& cs) : m_cs(cs) { m_cs.Enter(); }
        ~Locker() { m_cs.Leave(); }
    private:
        CriticalSection& m_cs;
    };

private:
    CRITICAL_SECTION m_cs;

Quote:
};

//... singleton pattern for a class (call it MyClass).

class MyClass
{
public:
    MyClass& GetInstance()
    {
        // Serialize access to the object.
        CriticalSection::Locker locker(m_instanceCs);

        // The singleton object.
        static MyClass myClass;
        return myClass;
    }

private:
    // Private constructor.
    MyClass()
    {
    // ...
    }

private:
    // Critical section.
    CriticalSection m_instanceCs;

Quote:
};

// Call with:

MyClass& myClass = MyClass::GetInstance();

HTH
Jay



Tue, 19 Jul 2005 00:53:45 GMT  
 thread-safe singleton?
Quote:

> Anyone have a good, simple thread-safe technique for forcing classes
> to only allow a single instantiation?

Use the "double checked locking" pattern :

Singleton& Singleton::Instance()
{
  if (!pInstance)
  {
     AcquireCriticalSectionOrMutex(....)
     if (!pInstance)
    {
      pInstance=new Singleton(....)
    }
    ReleaseCriticalSectionOrMutex(....)
  }
 return *pInstance;

Quote:
}

You do TWO checks, thus insuring that 2 threads cannot create the object
concurently, and yet avoiding to acquire the mutex / critical section each
time you ask for the singleton object.

Also, make the pInstance variable volatile.

Arnaud
MVP - VC



Tue, 19 Jul 2005 01:27:27 GMT  
 thread-safe singleton?

Quote:

> > Anyone have a good, simple thread-safe technique for forcing classes
> > to only allow a single instantiation?
> Use the "double checked locking" pattern :

... but you might want to read
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
for more background.  Double-checked locking can't be implemented
portably, in Java (which the article above discusses) or C++.

for Win32/x86, I don't think there's any problem with double-checked
locking since IA32 processors provide strong cache coherency and memory
ordering guarantees.

-cd



Tue, 19 Jul 2005 01:42:53 GMT  
 thread-safe singleton?


Fri, 19 Jun 1992 00:00:00 GMT  
 thread-safe singleton?
Not safe. Such a singleton can't be used in global objects'
constructors, because m_instanceCs may not have been constructed yet.
Allowing such usage is the whole point of having a static variable
inside GetInstance function (and the source of its thread-unsafety)
rather than making it a static member variable.
--
With best wishes,
    Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken


Quote:



> Should be this:

> ...
> private:
>     // Critical section.
>     static CriticalSection m_instanceCs;
> ...

> with:

> CriticalSection MyClass::m_instanceCs;

> in a CPP file somewhere.



Tue, 19 Jul 2005 02:31:48 GMT  
 thread-safe singleton?


Fri, 19 Jun 1992 00:00:00 GMT  
 thread-safe singleton?
There is a problem with this approach - how to create/initialize the
critical section or mutex before acquiring it. Essentially, the mutex
object is itself a singleton whose initialization needs protection, too.
--
With best wishes,
    Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken


Quote:

> > Anyone have a good, simple thread-safe technique for forcing classes
> > to only allow a single instantiation?
> Use the "double checked locking" pattern :

> Singleton& Singleton::Instance()
> {
>   if (!pInstance)
>   {
>      AcquireCriticalSectionOrMutex(....)
>      if (!pInstance)
>     {
>       pInstance=new Singleton(....)
>     }
>     ReleaseCriticalSectionOrMutex(....)
>   }
>  return *pInstance;
> }
> You do TWO checks, thus insuring that 2 threads cannot create the
object
> concurently, and yet avoiding to acquire the mutex / critical section
each
> time you ask for the singleton object.

> Also, make the pInstance variable volatile.



Tue, 19 Jul 2005 02:39:39 GMT  
 thread-safe singleton?


Fri, 19 Jun 1992 00:00:00 GMT  
 thread-safe singleton?


Quote:
> Not safe. Such a singleton can't be used in global objects'
> constructors, because m_instanceCs may not have been constructed yet.
> Allowing such usage is the whole point of having a static variable
> inside GetInstance function (and the source of its thread-unsafety)
> rather than making it a static member variable.
> --
> With best wishes,
>     Igor Tandetnik

Agreed. That's one reason why I have moved away from using global objects of
any complexity - the unpredicability of their construction and destruction
causes too much of a headache to allow (for me :). I much prefer a *single*
global object (perhaps an "Application" object) that encapsulates and
defines the order of the remaining "global" objects.

The code I posted works just fine in a multi-threaded case *except* for the
aforementioned unpredicability of global objects.

But your objection raises an interesting problem: given that any
synchronization object needs to be constructed before it's used, and given
that it can't be constructed on first use (you basically move the
non-thread-safeness to the construction of *that* object), is there a
solution that works for the random global object case? Perhaps a global
integer coupled with some Interlocked* functions, etc.? (I haven't worked
this out myself because I haven't needed to; just wondering if anyone else
had.)

Jay



Tue, 19 Jul 2005 02:41:25 GMT  
 thread-safe singleton?


Quote:
> Not safe. Such a singleton can't be used in global objects'
> constructors, because m_instanceCs may not have been constructed yet.

<emphasis>
Quote:
> Allowing such usage is the whole point of having a static variable
> inside GetInstance function (and the source of its thread-unsafety)
> rather than making it a static member variable.

</emphasis>

Not sure I agree with the emphasized assessment above.

Global objects (AFAIK) construct on the same thread, so there are no
threading issues if this is, indeed, "the whole point". (Any threads started
by those global objects are another matter entirely.)

The cases I've run into where threading is an issue are precisely those
where the singleton is *not* constructed before main(). For example, a
common resource accessed by multiple threads that only needs to be
constructed if the threads happen to come into existence and need it.
Threads fired up all hit the resource at once.

I guess all my threads are normally created *after* I get into main/WinMain,
so I never thought about *thread-safety* issues as being a global object
issue.

Jay



Tue, 19 Jul 2005 02:50:16 GMT  
 thread-safe singleton?

Quote:



> > Not safe. Such a singleton can't be used in global objects'
> > constructors, because m_instanceCs may not have been constructed
yet.

> <emphasis>
> > Allowing such usage is the whole point of having a static variable
> > inside GetInstance function (and the source of its thread-unsafety)
> > rather than making it a static member variable.
> </emphasis>

> Not sure I agree with the emphasized assessment above.

> Global objects (AFAIK) construct on the same thread, so there are no
> threading issues if this is, indeed, "the whole point". (Any threads
started
> by those global objects are another matter entirely.)

Well, here's the situation. If you implement the singleton naively, like
this:

class Singleton
{
private:
    static Singleton instance;
public:
    static Signleton& getInstance() {return instance;}

Quote:
};

it breaks for a single-threaded program where global objects try to use
the singleton in their constructors. The usual way to solve this problem
is like this:

class Singleton
{
public:
    static Signleton& getInstance()
    {static Signleton instance; return instance;}

Quote:
};

but then it breaks in a program where there are no global objects, but
two threads try to initialize the singleton at the same time. Thus
either implementation is unsafe in a reusable library.

I know two ways around this. One is the technique used to ensure that
std::cout is available to all global objects. You put the following into
the same .h file that defines the Singleton class:

namespace
{
    struct SingletonInit
    {
        SingletonInit() {Singleton::getInstance();}
    } initSingleton;

Quote:
};

This forces a getInstance call in every translation unit that might use
the Singleton. A (minor) disadvantage is that the singleton instance
gets initialized even if it is never used after all.

Another way is using OS-specific atomic integer operations, just as you
noted. Luckily, a global variable of a fundamental type gets its intial
value assigned before any code whatsoever is executed, so you can rely
on it being, say, 0 when the object is not initialized. You can then use
a manually implemented spinlock for synchronization.
--
With best wishes,
    Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken



Tue, 19 Jul 2005 04:01:44 GMT  
 
 [ 37 post ]  Go to page: [1] [2] [3]

 Relevant Pages 

1. An ATL7 implementation of a thread-safe singleton - is this the best way?

2. Why is function static singleton not thread-safe?

3. ANN: sigslot - C++ Portable, Thread-Safe, Type-Safe Signal/Slot Library

4. Using a non-thread-safe library with threads?

5. Thread functions are thread-safe?

6. how do i create thread safe worker thread

7. Singleton and multi threading.

8. Singleton and thread synchronization

9. Singleton not a singleton?

10. ATL Singleton and Singleton Class also from C++

11. Is NetworkStream.Write() thread safe?

12. Why OleDbCommand objects are not thread safe?

 

 
Powered by phpBB® Forum Software