thread-safe singleton?

This is a discussion on thread-safe singleton? within the C++ Programming forums, part of the General Programming Boards category; Code: static T& Instance() { static T t; return t; } apparently the above code isn't thread-safe. even if you ...

  1. #1
    Registered User
    Join Date
    Aug 2008
    Posts
    188

    thread-safe singleton?

    Code:
    static T& Instance()
    {
      static T t;
      return t;
    }
    apparently the above code isn't thread-safe. even if you wrap it around with critical sections, C++ generates code for the static variable like "if not null return" stuff, and since it's in the same critical section it's possible to return a null variable when it's already initialized.

    is the following code thread-safe?
    Code:
    class Foo
    {
    public:
      static T& Instance() { return _t; }
    private:
      static T _t;
    };

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,672
    >> is the following code thread-safe?
    Depends. Global object construction occurs before main(). However, other global objects can also be constructed prior to Foo which may access Foo::Instance(). Also, if the systems allows thread execution within the context of global object constructors (Windows does not) then there's the possibility of access to _t before it's been constructed.

    The easiest solution is to have a "static T *pt" and initialize it to zero. The first access to pt will then always be zero. Then use synchronization to access pt - if it's zero, create your once instance.

    gg

  3. #3
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,672
    >> ... (Windows does not) ...
    That's actually only for DLL's. In an EXE, global object constructors can create threads that start running immediately. In a DLL, global object constructors are performed within the context of DllMain() - which has restrictions on what you should and should not do. You can create threads, but they won't run until DllMain() returns - at which point all global objects are constructed.

    gg

  4. #4
    Registered User
    Join Date
    Aug 2008
    Posts
    188
    wow, thanks for the very informative responses.

  5. #5
    Registered User
    Join Date
    Nov 2006
    Posts
    519
    for thread safe singletonyou have to use pthread_once

    http://www.opengroup.org/onlinepubs/...read_once.html

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,672
    That's a good way to do if using pthreads. Here's the most recent documentation which is a little more descriptive: http://www.opengroup.org/onlinepubs/...read_once.html

    gg

  7. #7
    Registered User
    Join Date
    Nov 2006
    Posts
    519
    I forgot:
    if you are on win32, using pthread-w32, pthread_once seems broken, at least in the version I was using.

    Another option should be this:

    Code:
    main()
    {
      //call singleton as long is process is single threaded
      foo.instance(); //now it is initialized and ready
    
      //spawn your threads
      
      //call instance() from any thread
    }

  8. #8
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,627
    I simply don't understand why it's so hard to actually create the singleton at the start of main and then use the getSingleton method to access the singleton. Note that to be thread safe, the entire work on the singleton must be synchronized, not just the get method.

    Code:
    int main()
    {
        mysingleton_holder singleton; // First create the singleton
        mysingleton* p = singleton_holder::getsingleton(); // Now everywhere else you just use this
    }
    Or if you're really paranoid, you can guard the singleton constructor with a static variable and check if it's being instantiated more than once (in debug mode only).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,672
    Sometimes it's nice to have a true "on-demand" singleton - where it only gets created upon first access. For instance, if the construction of the singleton implies some sort of resource acquisition/usage, then you can delay that usage until it's needed (if at all).

    You may also want to remove all thread-safety responsibilities from the user - instead of requiring them to do something before creating threads.

    gg

  10. #10
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,627
    Quote Originally Posted by Codeplug View Post
    Sometimes it's nice to have a true "on-demand" singleton - where it only gets created upon first access. For instance, if the construction of the singleton implies some sort of resource acquisition/usage, then you can delay that usage until it's needed (if at all).
    I can see the use of that, sometimes.
    But it will also incur a delay each time you would access the singleton.
    Otherwise, it may be possible to use the above technique to just destroy the singleton once the program ends, since deleting singetons without hacks and trouble can be troublesome.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,596
    I always have a createInstance() and getInstance(). I've found very few, if any, ways to create exactly one singleton in a multithread environment. Even with double check locking it is possible to get two instances. The createInstance() is called once from one object and from that point on it is guaranteed to be created one time. Then getInstance() just returns that instance and does nothing else.

    As long as your design follows that every singleton will be created at X time by Y object(s) and at no other time then you should be ok.

    Another solution is to make the createInstance() private and then use a friend declaration for the class that is going to create or own the singleton. Friend here in this context is being used to enforce a rule of access to the function so for me it seems a valid use of it. Since createInstance() is private to everyone who is not a friend then no one else can call it w/o producing a compile time error which are my favorite types of errors. Of course someone can come behind you and just make themselves a friend but that is a clear misuse of the object in question. I do not condone the use of friend in many situations but other approaches to solve this problem frequently become more convoluted and complex than they are worth.

    As for shutdown and cleanup I too have seen destroyInstance() being used but I don't like it. Singleton, to me, implies the object will be alive for the duration of the program and will be cleaned up by the compiler upon shutdown. Trying to destroy the Singleton at any other time tells me that perhaps the Singleton pattern is not what should be used for an object that requires such behavior.
    Last edited by VirtualAce; 09-30-2008 at 05:45 PM.

  12. #12
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,261
    I always have a [...] does nothing else.
    Easy: don't use C++ to implement your locking mechanism.

    And "double check locking" doesn't guarantee anything valuable with most compilers; reordering of instructions means that your code is probably broken. (I think the latest MSVC actually produces the perfect code from simple C++, but this is hearsay, I haven't looked myself.)

    Soma

  13. #13
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,596
    I always have a [...] does nothing else.
    Easy: don't use C++ to implement your locking mechanism.

    If you don't want to rely on a specific platform or namely any mutexes, critical sections, etc. in Windows then I have no other idea other than the one I presented to ensure only one instance is created using the standard singleton pattern in a multi-thread environment.
    Last edited by VirtualAce; 10-01-2008 at 09:58 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. thread safe in my code to manipulate List?
    By George2 in forum C# Programming
    Replies: 8
    Last Post: 05-01-2008, 06:57 AM
  2. are winsock functions thread safe?
    By *DEAD* in forum Networking/Device Communication
    Replies: 2
    Last Post: 12-15-2007, 09:37 AM
  3. Replies: 2
    Last Post: 07-01-2007, 07:11 AM
  4. Calling a Thread with a Function Pointer.
    By ScrollMaster in forum Windows Programming
    Replies: 6
    Last Post: 06-10-2006, 08:56 AM
  5. C++ Threading?
    By draggy in forum C++ Programming
    Replies: 5
    Last Post: 08-16-2005, 12:16 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21