views:

184

answers:

6

What is the best way to destroy a singleton object?

case A: Single threaded Environment
case B: Multi Threaded Environment

Sample snippets(if any) will be really helpful.

[EDIT] I don't have a specific use case I am just trying to understand that IF AT ALL the singleton has to be used how to destroy it correctly. As i understand, from the comments, there are 2 scenarios possible:
1. Destroy the singleton when no code is accessing it.(use smart pointers which will take care of destroying the object by itself using RAII)
2. Destroy a singleton when exiting the program irrespective of whether or not some code was holding on to the singleton. (explicitly destroy by deleting the instance just before main exits)

+8  A: 

Don't create it in the first place!

Seriously, I strongly recommend you reconsider your choice of singleton, especially in a multithreaded environment. Instead just create an instance in main() and pass it down the call hierarchy to where it is needed.

You can use something like shared_ptr to ensure that the object stays around until no-one needs it any more.

Anthony Williams
I do understand the pitfalls of using singleton and as most of you mentioned it should be avoided but if one do has to use singleton, then what are the options? wrap it up in a smart pointer which employs reference counting can be option too, I am looking for possible solutions or workarounds.
Als
If you store the instance pointer in a smart pointer with static storage duration then it will be destroyed when the program exits.
Anthony Williams
@Als: why do you have to use a singleton? A singleton specifically *does not* allow you to destroy it (because then you no longer have a single instance)
jalf
A: 

In multi-threaded,

void Singleton::Destroy() 
{
  if (instance) { 
      pthread_mutex_lock(&lock);
      if (instance) { 
          delete instance;
          instance = 0x0;
      }
      pthread_mutex_unlock(&lock);
  }
}

In single-threaded:

void Singleton::Destroy() 
{
  if (instance) { 
      delete instance;
      instance = 0x0;
  }
}
Fanatic23
don't you mean 'if (instance)'?
filipe
@Arpan - Thanks! But the real problem i think is to ensure these destroy methods are called at the very end, when no resource needs the singleton anymore. I am trying to look for good solutions for that problem.
Als
This can lead to multiple instances of your singleton on true multiprocessor systems with per-CPU cache or even depending on how compiler uses registers. You need to ensure that "instance" comes from main memory before checking for instance!=0. That's one of the functions of mutex on modern machines. This link (http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html) is mostly about Java, but it also works for C++.
Arkadiy
Dont one use static MySingleton instance; return instance in these days?
InsertNickHere
@filipe Thanks, rectified that.
Fanatic23
@Als There's a difference between when no code accesses the singleton and when the program ends. Not sure when you want the singleton to be destroyed. Please clarify.
Fanatic23
+1  A: 

The backlash against the last decade's overuse of Singletons seem to be in rude health, but they're not entirely evil or unjustified... programming is about compromises and being practical, and it's hard to generalise (generally ;-P). By all means revisit the design and see if you can usefully get rid of them, but if not - so be it.

Anyway, if you want to understand the trade offs, you can't do better than start by reading Alexandrescu's Modern C++ Design, which devotes a chapter to the alternatives for Singletons. Basically, you're asking a silly question here because we don't know what operational constraints your singleton(s) have... what potential interactions, which resources they may need to use and whether they can be re-opened after being closed etc.. So, spit it out or settle for silly answers ;-P.

A: 

Leaving aside the question of if it is a good idea.
Which we should do in a separate question!

class S
{
    private:
        S() {}                // private constructor
        S(S const&);          // Undefined copy constructor
        S& operator(S const&) // Undefined assignment operator

    public:
        static S& getInstance()
        {
            /*
             * It is guaranteed to be built on first use
             * and correctly destroyed at the end of the application 
             */
            // Need guard for multi-threaded systems (but not on gcc)
            MULT_THREAD_GUARD;
            static S theOnlyInstance;
            return theOnlyInstance;
        }
};

The multi-thread initialization of the object is the only real problem. You can handle this two ways.

  • You can either put a GUARD to make sure only one thread can enter the getInstance() method when you do multi-threaded builds (iff you use gcc this is not required as it plants the required code automatically to guarantee the object is only initialized once).
  • The other technique is just to make sure the instance is initialized before any threads are created. To do this just call getInstance() in main. Mind you if you do this you may as well have a global variable as you destroy the main benefit of singletons over global variables (lazy initialization). Not that global variables are much better than singletons.

Example Guard

// Then in your platform agnostic header file
#ifndef MULTI_THREAD
#define MULT_THREAD_GUARD       /* Nothing needed in single threaded code */
#else
#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 3 ) && (__GNUC_MINOR__ > 1)))
#define MULT_THREAD_GUARD        /* Nothing required for GCC 3.2 onwards */
#elif defined(YOUR_COMPILERS_MACRO)
#define MULT_THREAD_GUARD        do { /* Put compiler lock code here */ } while (false)
#else
#error "ADD MULTI Thread GUARD for you compiler here"
#endif
Martin York
+1  A: 

If you're going to use a global, I prefer something like this:

class GlobalThing{ /* ... */ };

GlobalThing *global_thing = 0;

// ...

int main(){
  GlobalThing gt(/* ... */);
  global_thing = >

  // create threads
  // ...
  // kill threads
}

This gives you:

  1. An easily-identified lifetime for the global object.
  2. Resource cleanup in the typical RAII manner.
  3. The above points mean that it works in a multi-threaded environment without worrying about locks, etc., because no threads will exist before or after gt's lifetime. Well, in some environments, you can exit from main() and other threads will keep running, but that is a terrible way to architecture your program for a variety of reasons.

What you still have to worry about:

  1. Initialization order of globals. But, this is unlike the Static Initialization (and Destruction) Order Fiasco, because this technique gives you the benefit of defining the globals' initialization and destruction order (if you define them all this way).
  2. Something else, I'm sure.
Steve M
One of the "something else" things would be if anything references the global pointer before main runs, eg: other global/static object initialization. That's not to say those are architecturally good either, but it's another case which does happen in real code...
Nick
A: 

Might be able to use atexit() if you only care about cleaning up on successful shutdowns.

skimobear