Reputation: 206636
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)
Upvotes: 4
Views: 6483
Reputation: 1198
Might be able to use atexit() if you only care about cleaning up on successful shutdowns.
Upvotes: 2
Reputation: 3428
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;
}
}
Upvotes: 1
Reputation: 264699
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.
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
Upvotes: 1
Reputation: 8526
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:
What you still have to worry about:
Upvotes: 1
Reputation: 1053
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.
Upvotes: 1
Reputation: 68691
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.
Upvotes: 8