# Singleton Help

This topic is 3732 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Ok, I'm going to use a singleton pattern similar to the one by Scott Milas for things like CGraphics, CInput, CAudio because if more than one of these objects is lying around at the same time it currently completely flips. Now I've written it and it works single-threaded, I've tried to synchronize it, however I'm not sure wether its completely thread-safe yet.
template <class T> class CJT::Singleton
{
private:
static T* Instance;
static CCriticalSection CriticalSection;
public:
Singleton( void )
{
// Enter critical section, modifys static objects
CriticalSection.Enter();

// Check that the singleton hasn't already been created
if(Instance != NULL)
{
// Make sure the critical section is not orphoned
CriticalSection.Leave();

// Throw an exception
throw Exceptions::DuplicateSingleton();
}
Instance = static_cast <T*> (this);

// Leave critical section
CriticalSection.Leave();
}

~Singleton( )
{
// Enter critical section, modifys static objects
CriticalSection.Enter();

// Check that the singleton has been created
if(Instance == NULL)
{
// Make sure the critical section is not orphoned
CriticalSection.Leave();

// Throw an exception
throw Exceptions::InvalidSingleton();
}
Instance = NULL;

// Leave critical section
CriticalSection.Leave();
}

static T& GetSingleton()
{
// Enter critical section
CriticalSection.Enter();

// Check that the singleton is alive
if(Instance == NULL)
{
// Make sure the critical section is not orphoned
CriticalSection.Leave();

// Throw an exception
throw Exceptions::InvalidSingleton();
}

// Done here so that it is inside the critical section
T& Result = *Instance;

// Leave critical section
CriticalSection.Leave();

return Result;
}

static T* GetSingletonPtr()
{
// Enter critical section
CriticalSection.Enter();

// Done here so that it is inside the critical section
T& Result = *Instance;

// Leave critical section
CriticalSection.Leave();

return Instance;
}

static void Initialize()
{
new T();
}
static void CleanUp()
{
// Make sure that the singleton is alive
if(GetSingletonPtr() == NULL)
{
// Throw an exception
throw Exceptions::InvalidSingleton();
}
delete Instance;
}
};

// Static initializing
template <class T> T* CJT::Singleton <T>::Instance = NULL;
template <class T> CCriticalSection CJT::Singleton <T>::CriticalSection();

Thanks. PS: The CCriticalSection class shown in there isn't the MFC one, a custom one based on WinAPI critical sections.

##### Share on other sites
Firstly, that's not thread safe. You've made the create and destroy functions thread safe, but any other functions aren't.

Secondly, Don't use singletons.

##### Share on other sites
The singleton-related functionality is synchronized. However, use RAII, especially for locks and critical sections.

Also, the object itself will not be synchronized, so you'll have to lock it anyway.

As for using singletons, if the system does flip out when you use several instances, then it's a good idea as long as you respect elementary guidelines (such as not accessing the singleton directly, except once per thread).

##### Share on other sites
Quote:
 Original post by ganbreeNow I've written it and it works single-threaded, I've tried to synchronize it, however I'm not sure wether its completely thread-safe yet.

If singleton is mutable, it will always be single-threaded.

If it's immutable, it doesn't need synchronization at all.

For multi-threaded access it's customary to provide per-thread globals (no longer singletons, since multiple instances exist), and access them as such, without synchronization. TLS is a convenient way of implementing that.

##### Share on other sites
Quote:
 Original post by AntheusIn addition, whatever getInstance() returns must be thread-safe. As end-result, since every call *must* be synchronized, singletons reduce multi-threaded application to single-threaded one + overhead of synchronization.

... if there are collisions. For instance, if you perform a 10ms access in each thread once per second, collisions have a 3% chance of occuring, meaning you will run as multi-threaded most of the time.

##### Share on other sites
Why can't you just use a normal class, make one instance, and pass that around? You probably won't need those instances in more than a few other classes anyways. Global mutable state becomes a pain, just saying...

##### Share on other sites
ToohrVyk - By RAII do you mean by having a CCriticalSectionOwnership class and using scope to leave it instead of manually? I can see how that is better than my current implementation, added to the TODO list.

Now my use of a task and thread pool system should also reduce collision.

I'm currently thinking about what happens when ::CleanUp() is called while a Object& is still hanging around... Im not sure whether I need to explicitly initialize and clean up to singleton. Maybe I should have some kinda lazy initialization?

Evil Steve and Antheus, thanks for the all the singletons are evil posts. Your superiority complexes are really working overdrive today.

If the system breaks if there are multiple copies of a class then I should instead throw an exception to make the situation recoverable and debuggable. In doing so I am creating dead objects by throwing in their constructor, by doing so I am already enforcing that there can only be one valid instance of an object. Having dead objects lying around is dangerous, therfore a singleton is needed.

Does anyone have any help with the implementation of a thread safe singleton?

##### Share on other sites
Quote:
 Original post by ganbreeEvil Steve and Antheus, thanks for the all the singletons are evil posts. Your superiority complexes are really working overdrive today.
I'm simply pointing out that this is one of the problems with singletons. Singletons are really just globals in disguise.

As for a thread safe singleton, you just have to make sure that every member function of the singleton is synchronised with a critical section.

##### Share on other sites
Ok, maybe I shouldn't have said something like that.

Sorry.

##### Share on other sites
Quote:
 Evil Steve and Antheus, thanks for the all the singletons are evil posts. Your superiority complexes are really working overdrive today.
It can be argued that a singleton is an appropriate solution only when it would be an error for there to be multiple instances, and when global access is required. It can also be argued that there is no need for objects that handle such things as graphics, audio, and input to be global, and that in fact it would be better if they weren't.

As such, it doesn't seem unreasonable to suggest that singletons might not be the best solution to your problem, and to provide you with references that provide more information on the subject.

1. 1
Rutin
26
2. 2
3. 3
4. 4
5. 5

• 9
• 11
• 10
• 13
• 20
• ### Forum Statistics

• Total Topics
632948
• Total Posts
3009390
• ### Who's Online (See full list)

There are no registered users currently online

×