• Advertisement
Sign in to follow this  

Singleton Help

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
Share on other sites
Quote:
Original post by ganbree

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.


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

In 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 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 this post


Link to post
Share on other sites
Quote:
Original post by Antheus
In 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.

If any synchronized access to data caused single-threading, then we couldn't share data between threads, could we?

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by ganbree
Evil 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 this post


Link to post
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement