Singleton Pattern
Classic Singleton
#include
using namespace std;
class Single {
public:
static Single* getinstance() {
if(instance == NULL) {
instance = new Single();
cout << "object returned" << endl;
}
return instance;
}
void fun() {
cout << "Single class" << endl;
}
private:
static Single* instance;
static int counter;
Single() { };
Single(const Single& obj);
// need to comment it, to call getInstance() again to print address
//Single& operator=(const Single& obj);
};
Single* Single::instance = NULL;
/* we should get same address everytime */
int main()
{
Single *obj = Single::getinstance();
cout << "obj address=" << hex << obj << endl;
obj->fun();
cout << "obj address=" << hex << Single::getinstance() << endl;
cout << "obj address=" << hex << Single::getinstance() << endl;
Single::getinstance()->fun();
}
Multiton with counter
#include
using namespace std;
class Multi {
public:
// multiton
static Multi* getinstance() {
if (counter < 2) {
instance = new Multi();
++counter;
cout << "counter:" << counter << endl;
}
return instance;
}
void fun() {
cout << "Single class" << endl;
}
private:
static Multi* instance;
static int counter;
Multi() { };
Multi(const Multi& obj);
// need to comment it, to call getInstance() again to print address
//Multi& operator=(const Multi& obj);
};
Multi* Multi::instance = NULL;
int Multi::counter = 0;
int main()
{
Multi *obj = Multi::getinstance();
obj->fun();
cout << "obj address=" << hex << obj << endl;
Multi *obj1 = Multi::getinstance();
cout << "obj1 address=" << hex << obj1 << endl;
Multi *obj2 = Multi::getinstance();
cout << "obj2 address=" << hex << &obj2 << endl;
Multi *obj3 = Multi::getinstance();
cout << "obj3 address=" << hex << &obj3 << endl;
}
It doesn’t work, go for next one
Singleton (Double Checked Locking/Thread Safe)
#include
using namespace std;
#include // std::mutex, std::lock_guard
#include // std::logic_error
#include // std::thread
std::mutex mtx;
class Single {
public:
static Single* getinstance() {
if(instance == NULL) {
try {
std::lock_guard lck (mtx);
if(instance == NULL) {
instance = new Single();
cout << "object returned" << endl;
}
}
catch (std::logic_error&) {
std::cout << "[exception caught]\n";
}
}
return instance;
}
void fun() {
cout << "Single class" << endl;
}
private:
static Single* instance;
Single() { };
Single(const Single& obj);
// need to comment it, to call getInstance() again to print address
//Single& operator=(const Single& obj);
};
Single* Single::instance = NULL;
/* we should get same address everytime */
int main()
{
std::thread threads[10];
// spawn 10 threads:
for (int i=0; i<10 i="" span="">10>
threads[i] = std::thread(Single::getinstance);
//*threads[i]->fun();
}
for (auto& th : threads) th.join();
/*
Single *obj = Single::getinstance();
cout << "obj address=" << hex << obj << endl;
obj->fun();
cout << "obj address=" << hex << Single::getinstance() << endl;
cout << "obj address=" << hex << Single::getinstance() << endl;
Single::getinstance()->fun();
*/
}
Note: Usage in main is some what not correct, need to relook
Multiton with key-value pair
#include
#include
using namespace std;
class Multi {
public:
// multiton
static Multi* getinstance(int key) {
map::iterator it = instance.find(key);
if(it != instance.end())
return (Multi*) (it->second);
instance[key] = new Multi();
return (Multi*) instance[key];
}
void fun() {
cout << "Single class" << endl;
}
private:
static map instance;
Multi() { };
Multi(const Multi& obj);
// need to comment it, to call getInstance() again to print address
//Multi& operator=(const Multi& obj);
};
map Multi::instance; // static map initialization
//
int main()
{
Multi *obj1 = Multi::getinstance(1);
obj1->fun();
cout << "obj1 address=" << hex << obj1 << endl;
cout << "obj2 address=" << hex << Multi::getinstance(2) << endl;
cout << "obj3 address=" << hex << Multi::getinstance(1) << endl;
cout << "obj4 address=" << hex << Multi::getinstance(2) << endl;
cout << "obj5 address=" << hex << Multi::getinstance(1) << endl;
cout << "obj6 address=" << hex << Multi::getinstance(2) << endl;
}
Meyers Singleton
#include
using namespace std;
class Single {
public:
// meyers singleton
static Single& getInstance() {
static Single stat_instance;
return stat_instance;
}
void fun() {
cout << "Single class" << endl;
}
private:
Single() { };
Single(const Single& obj);
// need to comment it, to call getInstance() again to print address
//Single& operator=(const Single& obj);
};
int main()
{
Single& obj = Single::getInstance();
obj.fun();
cout << "obj address=" << hex << &obj << endl;
obj = Single::getInstance();
cout << "obj address=" << hex << &obj << endl;
}
Singleton discovered late
#include
#include
using namespace std;
class Single {
public:
void* operator new(size_t size) {
if (!instance) {
instance = (Single *) malloc(size);
}
return instance;
}
void fun() {
cout << "Single class" << endl;
}
Single() {};
Single(const Single& obj);
Single& operator=(const Single& obj);
private:
static Single* instance;
};
Single* Single::instance = NULL;
int main()
{
Single *obj = new Single();
obj->fun();
cout << "obj address=" << hex << obj << endl;
cout << "obj address=" << hex << new Single() << endl;
cout << "obj address=" << hex << new Single() << endl;
}
Multiton discovered late
#include
#include
#include
using namespace std;
class Multi {
public:
static void* operator new(size_t size, int key) {
map::iterator it = instance.find(key);
if(it != instance.end())
return (Multi*) (it->second);
//instance[key] = (Multi *) malloc(size); OR
instance[key] = (Multi *) ::operator new(size);
return (Multi*) instance[key];
}
void fun() {
cout << "Single class" << endl;
}
Multi() { };
Multi(const Multi& obj);
Multi& operator=(const Multi& obj);
private:
static map instance;
};
map Multi::instance;
int main()
{
Multi *obj = new (1) Multi();
obj->fun();
cout << "obj address=" << hex << obj << endl;
cout << "obj address=" << hex << new (2) Multi() << endl;
cout << "obj address=" << hex << new (1) Multi() << endl;
cout << "obj address=" << hex << new (2) Multi() << endl;
}
Note: Once challenge which I see is everywhere we have to pass params to new operator