Is this Singleton class thread-safe?

Discussion in 'C++' started by Angus, Nov 14, 2007.

  1. Angus

    Angus Guest

    Hello

    I have written a singleton class like this:

    //---------------------------------------------------------------------------
    // Instance
    //---------------------------------------------------------------------------
    template <typename T>
    T * CSingleton<T>::Instance(
    ) throw()
    {
    static T inst;
    return &inst;
    }

    Is this thread safe? Could two threads (with cpu context switching)
    possibly create more than one instance of the class passed as a
    template? Is this possible? If it is I presume I must lock using
    mutex or some mechanism before line - static T inst; and just after
    it?

    Angus
     
    Angus, Nov 14, 2007
    #1
    1. Advertising

  2. Angus

    DJ Guest

    Angus napisał(a):
    > Hello
    >
    > I have written a singleton class like this:
    >
    > //---------------------------------------------------------------------------
    > // Instance
    > //---------------------------------------------------------------------------
    > template <typename T>
    > T * CSingleton<T>::Instance(
    > ) throw()
    > {
    > static T inst;
    > return &inst;
    > }
    >
    > Is this thread safe? Could two threads (with cpu context switching)
    > possibly create more than one instance of the class passed as a
    > template? Is this possible? If it is I presume I must lock using
    > mutex or some mechanism before line - static T inst; and just after
    > it?


    It is not thread safe and you must lock it, however mutex lock might
    give performace penalty - depends on yours app. There is something
    called double-checking locking - google for that - it's well known and
    described problem
     
    DJ, Nov 14, 2007
    #2
    1. Advertising

  3. Angus

    Pete Becker Guest

    On 2007-11-14 12:35:27 -0500, Angus <> said:

    > Hello
    >
    > I have written a singleton class like this:
    >
    > //---------------------------------------------------------------------------
    > // Instance
    > //---------------------------------------------------------------------------
    > template <typename T>
    > T * CSingleton<T>::Instance(
    > ) throw()
    > {
    > static T inst;
    > return &inst;
    > }
    >
    > Is this thread safe?


    The language definition doesn't say, because it doesn't deal with
    threads. Check the documentation for your compiler.

    --
    Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
    Standard C++ Library Extensions: a Tutorial and Reference
    (www.petebecker.com/tr1book)
     
    Pete Becker, Nov 14, 2007
    #3
  4. DJ wrote:
    > Angus napisał(a):
    >> Hello
    >>
    >> I have written a singleton class like this:
    >>
    >> //---------------------------------------------------------------------------
    >>
    >> // Instance
    >> //---------------------------------------------------------------------------
    >>
    >> template <typename T>
    >> T * CSingleton<T>::Instance(
    >> ) throw()
    >> {
    >> static T inst;
    >> return &inst;
    >> }
    >>
    >> Is this thread safe? Could two threads (with cpu context switching)
    >> possibly create more than one instance of the class passed as a
    >> template? Is this possible? If it is I presume I must lock using
    >> mutex or some mechanism before line - static T inst; and just after
    >> it?

    >
    > It is not thread safe and you must lock it, however mutex lock might
    > give performace penalty - depends on yours app. There is something
    > called double-checking locking - google for that - it's well known and
    > described problem



    Some compilers do make sure it's thread safe (see G++ past V4).

    DCL (double checked locking) is not considered a good thing because it
    does not work on all machines - see past articles on
    comp.programing.threads.
     
    Gianni Mariani, Nov 14, 2007
    #4
  5. Angus

    DJ Guest

    Gianni Mariani napisał(a):
    > DJ wrote:
    >
    >> Angus napisał(a):
    >>
    >>> Hello
    >>>
    >>> I have written a singleton class like this:
    >>>
    >>> //---------------------------------------------------------------------------
    >>>
    >>> // Instance
    >>> //---------------------------------------------------------------------------
    >>>
    >>> template <typename T>
    >>> T * CSingleton<T>::Instance(
    >>> ) throw()
    >>> {
    >>> static T inst;
    >>> return &inst;
    >>> }
    >>>
    >>> Is this thread safe? Could two threads (with cpu context switching)
    >>> possibly create more than one instance of the class passed as a
    >>> template? Is this possible? If it is I presume I must lock using
    >>> mutex or some mechanism before line - static T inst; and just after
    >>> it?

    >>
    >>
    >> It is not thread safe and you must lock it, however mutex lock might
    >> give performace penalty - depends on yours app. There is something
    >> called double-checking locking - google for that - it's well known and
    >> described problem

    >
    >
    >
    > Some compilers do make sure it's thread safe (see G++ past V4).


    I am just thinking if you call ::Instace before threads are created in
    the app you should be fine as the static object must be created,
    shoudn't you ?
    >
    > DCL (double checked locking) is not considered a good thing because it
    > does not work on all machines - see past articles on
    > comp.programing.threads.


    true.
     
    DJ, Nov 14, 2007
    #5
  6. DJ wrote:
    ....
    > I am just thinking if you call ::Instace before threads are created in
    > the app you should be fine as the static object must be created,
    > shoudn't you ?


    Yes.

    >>
    >> DCL (double checked locking) is not considered a good thing because it
    >> does not work on all machines - see past articles on
    >> comp.programing.threads.

    >
    > true.
     
    Gianni Mariani, Nov 14, 2007
    #6
  7. Angus

    James Kanze Guest

    On Nov 14, 6:35 pm, Angus <> wrote:
    > I have written a singleton class like this:


    > //---------------------------------------------------------------------------
    > // Instance
    > //---------------------------------------------------------------------------
    > template <typename T>
    > T * CSingleton<T>::Instance(
    > ) throw()
    > {
    > static T inst;
    > return &inst;
    > }


    > Is this thread safe?


    Maybe. You've cut the documentation which states its
    requirements, so there's no way to tell.

    > Could two threads (with cpu context switching) possibly create
    > more than one instance of the class passed as a template? Is
    > this possible?


    Possibly. It depends on whether two threads have a right to do
    this or not.

    If you want to allow multiple threads to call Instance without
    external locking, you'll probably have to take some precautions
    internally.

    > If it is I presume I must lock using mutex or some mechanism
    > before line - static T inst; and just after it?


    There are other solutions, depending on the context:

    -- You could just document that the user must externally
    synchronize calls to Instance. If the user needs external
    synchronization to use the returned object anyway, this is
    perfectly acceptable, and doubtlessly the simplest solution.

    -- If you don't need to support multithreading before main is
    called, something like:

    T* Singleton<T>::eek:urInstance = Singleton<T>::instance() ;

    Singleton<T>*
    Singleton<T>::instance()
    {
    return ourInstance == NULL
    ? new T
    : ourInstance ;
    }

    can be used. This works if (and only if) instance() is
    called at least once before threading starts; the
    initializer of ourInstance guarantees that it will be called
    at least once before main() is entered (in practice, if not
    necessarily formally).

    This is what I tend to do in generic solutions, or when T is
    mainly a read-only object. (Note that this has the
    additional advantage that the instance is never destructed,
    so you don't run into order of destructor problems either.)

    -- If the user absolutly needs external synchronization to use
    the object, you can provide it for him, by returning a smart
    pointer which reference counts, and whose last instance
    unlocks, and grab the lock before starting. Something like:

    pthread_mutex_t ourLock = PTHREAD_MUTEX_INITIALIZER ;

    struct Unlocker
    {
    void operator()() {
    pthread_mutex_unlock( &ourLock ) ;
    }
    } ;

    boost::shared_ptr< T >
    Singleton::instance()
    {
    pthread_mutex_lock( &ourLock ) ;
    static T* theOneAndOnly = NULL ;
    if ( theOneAndOnly == NULL ) {
    theOneAndOnly = new Singleton ;
    }
    return boost::shared_ptr< T >( theOneAndOnly,
    Unlocker() ) ;
    }

    Once again, the only lock you've acquired is one that the
    user needed anyway.

    (I don't think that this solution is appropriate for generic
    code, but it seems a nice idea for some special cases.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Nov 15, 2007
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?V2lsbGlhbSBTdWxsaXZhbg==?=

    Thread safe singleton to access the cache?

    =?Utf-8?B?V2lsbGlhbSBTdWxsaXZhbg==?=, Oct 6, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    789
    Bruce Barker
    Oct 6, 2005
  2. Anand
    Replies:
    11
    Views:
    9,885
    Jacob
    Feb 10, 2006
  3. Gabriel Rossetti
    Replies:
    0
    Views:
    1,330
    Gabriel Rossetti
    Aug 29, 2008
  4. Udit Sharma

    Thread safe Singleton class

    Udit Sharma, Jun 26, 2009, in forum: C++
    Replies:
    4
    Views:
    2,700
    Alf P. Steinbach
    Jun 26, 2009
  5. John Nagle
    Replies:
    5
    Views:
    475
    John Nagle
    Mar 12, 2012
Loading...

Share This Page