Single case design pattern, shared data analysis and solution, call_once

Keywords: C++ Concurrent Programming

Section 7 single case design pattern, shared data analysis, solution, call_once

1. Design mode

  • The program is flexible and easy to maintain. The code written with the concept of design pattern is very obscure, but it will be painful for others to take over and read the code
  • When foreigners deal with particularly large projects, they summarize and sort out the project development experience and module division experience into design patterns
  • At the beginning of the popularity of Chinese design patterns in the past few years, they always liked to apply one design pattern to the top, resulting in a small project always adding several design patterns, putting the cart before the horse
  • Design mode has its unique advantages. We should learn and use it flexibly. Don't get trapped and copy mechanically

2. Single case design mode:
In the whole project, there is a certain or some special class, and only one object belonging to this class can be created.
Singleton class: only one object can be generated.

3. Shared data analysis and solution of single case design mode
Problem: you need to create singleton objects in your own thread. There may be more than one such thread. We may face that member functions such as GetInstance() need to be mutually exclusive.
You can judge m before locking_ Whether instance is empty or not. Otherwise, every time Singleton::getInstance() is called, it will be locked, which will greatly affect the efficiency.

#include <iostream>	
#include <mutex>
using namespace	std;
mutex myMutex;
//Lazy mode
class Singleton
{
public:
	static Singleton * getInstance() {
         //Double locking improves efficiency
		if (instance == NULL) {
			lock_guard<mutex> myLockGua(myMutex);
			if (instance == NULL) {
				instance = new Singleton;
			}
		}
		return instance;
	}
private:
	Singleton() {}
	static Singleton *instance;
};
Singleton * Singleton::instance = NULL;
//Hungry man model
class Singleton2 {
public:
	static Singleton2* getInstance() {
		return instance;
	}
private:
	Singleton2() {}
	static Singleton2 * instance;
};
Singleton2 * Singleton2::instance = new Singleton2;
int main(void)
{
	Singleton * singer = Singleton::getInstance();
	Singleton * singer2 = Singleton::getInstance();
	if (singer == singer2)
		cout << "They are the same instance" << endl;
	else
		cout << "They are not the same instance" << endl;
	cout << "----------		The following is the hungry Chinese style	------------" << endl;
	Singleton2 * singer3 = Singleton2::getInstance();
	Singleton2 * singer4 = Singleton2::getInstance();
	if (singer3 == singer4)
		cout << "They are the same instance" << endl;
	else
		cout << "They are not the same instance" << endl;
	return 0;
}

It is unreasonable to think that an object is created in the singleton mode without deleting it. You can add a class CGarhuishou in a class. When a new singleton class is created, a static CGarhuishou object will be created. In this way, the destructor of CGarhuishou will be called at the end of the program to release the singleton object from new.

class Singelton
{
public:
	static Singleton * getInstance() {
        if (instance == NULL) {
		    static CGarhuishou huishou;
		    instance = new Singelton;
        }
        return instance;
	}
	class CGarhuishou {
	public:
		~CGarhuishou()
		{
			if (Singleton::instance)
			{
				delete Singleton::instance;
				Singleton::instance = NULL;
			}
		}
	};
private:
	Singleton() {}
	static Singleton *instance;
};
Singleton * Singleton::instance = NULL;

4.std::call_once():
Function template. The first parameter of the function is a tag, and the second parameter is a function name (such as a()).
Function: it can ensure that function a() is called only once. It has the ability of mutex, and consumes less resources and is more efficient than mutex.
call_once() needs to be used in conjunction with a tag called std::once_flagļ¼› Actually once_flag is a structure called call_once() determines whether the function is executed through the tag. After the call is successful, the tag is set to a called state.

When multiple threads execute at the same time, one thread will wait for another thread to execute first.

once_flag g_flag;
class Singleton
{
public:
    static void CreateInstance()//call_once ensures that it is called only once
    {
        instance = new Singleton;
    }
    //Two threads execute here at the same time. One thread has to wait for the other thread to finish executing
	static Singleton * getInstance() {
         call_once(g_flag, CreateInstance);
         return instance;
	}
private:
	Singleton() {}
	static Singleton *instance;
};
Singleton * Singleton::instance = NULL;

Posted by big.nerd on Sat, 16 Oct 2021 21:31:28 -0700