Singleton: Difference between revisions

Content added Content deleted
(→‎{{header|Kotlin}}: Updated example see https://github.com/dkandalov/rosettacode-kotlin for details)
(→‎{{header|C++}}: A proper implementation should only (1) ensure that only one instance exists at any given moment; and (2) provide global access to that instance. Concurrency issues should be considered as a separate matter (in the general case).)
Line 201: Line 201:


=={{header|C++}}==
=={{header|C++}}==
A generic singleton template class (implemented via the "Curiously Recurring Template Pattern"[https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern]). Warning: if using a version of C++ prior to C++11, a [[Mutex#C|mutex]] (or similar) is required to access static variables within a multi-threaded program.
===Thread-safe===
'''Operating System:''' Microsoft Windows NT/XP/Vista
:Uses a [[Win32]] flavor [[Mutex#Win32|Mutex]] - a [[POSIX]] flavor [[Mutex#POSIX|Mutex]] could be used.
<lang cpp>class Singleton
{
public:
static Singleton* Instance()
{
// We need to ensure that we don't accidentally create two Singletons
HANDLE hMutex = CreateMutex(NULL, FALSE, "MySingletonMutex");
WaitForSingleObject(hMutex, INFINITE);


<lang cpp>
// Create the instance of the class.
#include <stdexcept>
// Since it's a static variable, if the class has already been created,
// It won't be created again.
static Singleton myInstance;


template <typename Self>
// Release our mutex so that other application threads can use this function
class singleton
ReleaseMutex( hMutex );
{
protected:
static Self*
sentry;
public:
static Self&
instance()
{
return *sentry;
}
singleton()
{
if(sentry)
throw std::logic_error("Error: attempt to instantiate a singleton over a pre-existing one!");
sentry = (Self*)this;
}
virtual ~singleton()
{
if(sentry == this)
sentry = 0;
}
};
template <typename Self>
Self*
singleton<Self>::sentry = 0;


/*
// Free the handle
Example usage:
CloseHandle( hMutex );
*/


#include <iostream>
// Return a pointer to our mutex instance.
#include <string>
return &myInstance;
}


using namespace
// Any other public methods
std;


class controller : public singleton<controller>
protected:
Singleton()
{
// Constructor code goes here.
}
~Singleton()
{
// Destructor code goes here.
}

// And any other protected methods.
}</lang>

===Non-Thread-Safe===
This version doesn't require [[Mutex#C|Mutex]], but it is not safe in a multi-threaded environment (before C++11).
<lang cpp>class Singleton
{
{
public:
public:
controller(string const& name)
static Singleton* Instance()
: name(name)
{
{
// Since it's a static variable, if the class has already been created,
trace("begin");
// It won't be created again.
}
static Singleton myInstance;
~controller()

{
// Return a pointer to our mutex instance.
trace("end");
return &myInstance;
}
}
void

work()
// Any other public methods
{

trace("doing stuff");
protected:
}
Singleton()
void
{
trace(string const& message)
// Constructor code goes here.
{
}
cout << name << ": " << message << endl;
~Singleton()
}
{
string
// Destructor code goes here.
name;
}
};

int
// And any other protected methods.
main()
}</lang>

=== Thread safe (since C++11) ===
This will be thread safe since C++11, where static variables is always thread-safe (according to section 6.7 of The Standard).

<lang cpp>class Singleton
{
{
controller*
public:
first = new controller("first");
static Singleton & Instance()
controller::instance().work();
{
delete first;
// Since it's a static variable, if the class has already been created,
/*
// It won't be created again.
No problem, our first controller no longer exists...
// And it **is** thread-safe in C++11.
*/

controller
static Singleton myInstance;
second("second");

controller::instance().work();
// Return a reference to our instance.
try
return myInstance;
{
}
/*
Never happens...
// delete copy and move constructors and assign operators
*/
Singleton(Singleton const&) = delete; // Copy construct
controller
Singleton(Singleton&&) = delete; // Move construct
goner("goner");
Singleton& operator=(Singleton const&) = delete; // Copy assign
controller::instance().work();
Singleton& operator=(Singleton &&) = delete; // Move assign
}

catch(exception const& error)
// Any other public methods
{

cout << error.what() << endl;
protected:
}
Singleton()
controller::instance().work();
{
/*
// Constructor code goes here.
Never happens (and depending on your system this may or may not print a helpful message!)
}
*/

controller
~Singleton()
goner("goner");
{
controller::instance().work();
// Destructor code goes here.
}
}
</lang>

// And any other protected methods.
}</lang>


=={{header|C sharp|C#}}==
=={{header|C sharp|C#}}==