Some basics for a new job

YAML

YAML Getting Started Tutorial | Novice Tutorial YAML is a recursive acronym for 'YAML Ain't a Markup Language' (YAML is not a markup language). At the time the language was developed, YAML actually stood for: 'Yet Another Markup Language' (still a markup language). The syntax of YAML is similar to other high-level languages, and it can simply express data forms such as lists, hash tables, and scalars. It uses whitespace indentation and a lot of appearance-dependent features, especially suitable for expressing or editing data.. https://www.runoob.com/w3cnote/yaml-intro.html

ISO 8601

​​​​​​Learn what is ISO 8601Learn what is ISO 8601 p71M * -HPe5dNpVQyUwfJvFby5-NNuf9qfTGYEGgPaVQXhiQ1Z9LzQeEZ*gfy3VlwjRlqX&new=1

ROBIN_SET

robin-map: fast hash_map and hash_set bzdww

robin-map is a fast hash map and hash set written in c++, providing fast insertion, search and deletion operations.

Key Features

  1. header only
  2. high speed
  3. efficient serialization
  4. API similar to std::unordered_map and std::unordered_set
  5. MY license

boost::noncopyable,

class please_dont_make_copies : boost::noncopyable {};

int main() {
please_dont_make_copies d1;
please_dont_make_copies d2(d1);
please_dont_make_copies d3;
d3=d1;
}

This example fails to compile. Since Noncopyable's copy constructor is private, attempts to copy-construct d2 fail. Likewise, an attempt to assign d1 to d3 fails because the noncopyable assignment operator is also private.

UT,IT,ST,UAT

UT, IT, ST, UAT refer to unit testing, integration testing, system testing, user acceptance testing.

What are CIs? What is the difference between CI and CD?

The acronym CI/CD has several different meanings. The "CI" in CI/CD always refers to continuous integration, which is an automated process for developers. Successful CI means that new changes to the application code are regularly built, tested, and merged into the shared repository. This solution can solve the problem of having too many application branches in one development, resulting in conflicts.

The "CD" in CI/CD refers to continuous delivery and/or continuous deployment, and these related concepts are sometimes used interchangeably. Both relate to the automation of subsequent stages of the pipeline, but they are also sometimes used on their own to illustrate the degree of automation

Specifically, CI/CD enables continuous automation and continuous monitoring throughout the application lifecycle (from integration and testing phases, to delivery and deployment). These associated transactions are often collectively referred to as "CI/CD pipelines" and are collaboratively supported by development and operations teams in an agile fashion.

_access

win:int _access(char* path,int mode)

gnu:access

Header file <io.h>
Function: determine the access rights of files or folders. If the specified access mode is valid, the function returns 0, otherwise the function returns -1.
The parameter path is the path name where the access file is located, and mode is the access judgment mode. The
specific meanings are as follows:
  R_OK only judges whether there is read permission
  W_OK only judges whether there is write permission
  X_OK judges whether there is execution permission
  F_OK only judges whether it exists

I have also used fopen to determine whether a file exists before, but the _access function is more convenient.

eg:

nFileExit = _access(strnew.c_str(),0);
if(nFileExit == 0)
{
    CopyFile(strfilename.c_str(), strnew.c_str(), 0);

else
{

}

GetPrivateProfileString

GetPrivateProfileString(lpszSection, lpszKey, lpszDefault, lpszReturnBuffer, cchReturnBuffer, lpszFile)
lpszSection: ini文件中小节的名称,格式[name]

lpszKey:  条目名称

lpszDefault: 当没有读取到对应条目值时,以此值返回, 一般设为NULL

lpszReturnBuffer: 存放所读取的空间

lpszfile: ini 文件绝对名称

#include <cstdlib>
#include <iostream>
#include <Windows.h>


using namespace std;


char    IP_addr[128] = {'\0'};
char    IP_addr_1[128] = {'\0'};

int main(int argc, char *argv[])
{
    cout << g_IP_addr_1<<" here is IP_addr_1"<<endl;
    int len=0;
    len= GetPrivateProfileStringA("TESTER_SETUP","IP_ADDRESS_1",NULL,IP_addr_1,sizeof(IP_addr),".\\Setup.ini");
    //if(0!= len)
    cout << g_IP_addr_1<<endl << " here is IP_addr_1"<<endl;
    
    
    system("PAUSE");
    return EXIT_SUCCESS;
}

INI file:

[TESTER_SETUP]
IP_ADDRESS_1= 192.168.100.254

————————————————

fetch_add()

fetch_sub()

Perform atomic operation +1 -1 on a number, generally used in reference counting;

Inline functions and macro definitions

: When the compiler finds that a certain piece of code is calling an inline function, it does not call the function, but inserts the entire code of the function into the current position. The advantage of this is that the process of calling is omitted, and the running speed of the program is accelerated. (The calling process of the function always takes more time due to the operations such as pushing the parameters into the stack mentioned above). The disadvantage of this is that whenever the code calls an inline function, a piece of code for the function needs to be inserted directly at the call site, so the size of the program will increase

1. The inline function is the same as the function in terms of readability, but the function is directly embedded in the body of the calling program at compile time, eliminating the need for call/return instructions, which is faster at runtime.

2. Inline functions can be debugged, but macro definitions cannot be debugged.
Inline functions and macros are essentially two different concepts. If the program writer requires both speed and readability, the function should be called inline. Let's take a closer look at inline functions and macro definitions

a. Inline functions need to be type-checked when compiling, and then the code is expanded at the function call point; while the macro definition is a simple replacement without any checks at the code. From this point of view, inline functions are safer.
b. The inline function is a function, but it does not generate code separately at compile time, but embeds the relevant code into the calling place; while the macro definition is not a function, but replaces the relevant string with the macro body in the preprocessing stage of compilation
———— ———————————

Header files related to C++11 multithreading

The new C++11 standard introduces four header files to support multi-threaded programming, they are <atomic>, <thread>, <mutex>, <condition_variable> and <future>. 

Thread Use thread class, more excellent cross-platform

Mutexes and locks are also excellent cross-platform.

std:: thread

C++——Multithreaded Programming (1) std::thread_linyyy's Blog - CSDN Blog

std::ref function_Ch_zaqdt's Blog - CSDN Blog_The role of std::ref

     The std::ref function of C++11 is to solve the problem of value copying in the process of creating a thread. The following will use the creation of a thread to demonstrate the function of the ref function.

 Because the memory address of the object in the fun function and the object in the main function are different, if we want to modify the value of this object in the fun function, it will not work in the main, which will lose the reference a role

    It can be seen that the copy constructor is not called in the process of parameter passing, and the memory address is the same, and the changed value also achieves the effect we want, but in order to ensure the safety of the thread, this method cannot use detach to make the main thread and the child Threads separate.

 The function of the join() method is to let the main thread wait for the child thread to finish executing before running the main thread

What is mutable good for? What if I want to modify a member variable of an object inside a constant member function? At this time, mutable needs to be introduced to define the member variable of the object as a mutable variable. However, we will regard the variable defined as mutable as a state that does not belong to the object. In this way, mutable variables can be modified even inside the constant member function. At the same time, inside the constant member function, other member variables of the object (that is, the internal state of the object) cannot be modified
———————— ———————

mutex和recursive_mutex

void lock()

There are three situations in which mutex uses locks.

1. If no thread uses mutex, the calling thread uses mutex

2. If other threads use the mutex, the currently calling thread will be blocked until other threads using the lock are released.

3. If the mutex is called by the same thread, a deadlock will occur

recursive_mutex is similar to mutex, if no thread is used, it is locked

Block if used by a thread

If the same thread uses a mutex, add a new layer of mutex, and when the corresponding release, you need to unlock() once more

std::this_thread::sleep_for

Blocks the current thread from executing, at least as long as specified  sleep_duration.

This function may block longer than  sleep_durationbecause of scheduling or resource dispute delays.

The standard library recommends measuring time with a stable clock. Wait times may also be sensitive to clock adjustments if the implementation uses system time instead

lock_guard

Compared with the mutex function, lock_guard has the function of locking when creating and unlocking when destructing, similar to smart pointers. In order to prevent the problem of deadlock caused by abnormal exit after the thread uses mutex to lock, it is recommended to use lock_guard instead of mutex. The following code demonstrates the function:

lock_guard has two construction methods:

  1. lock_guard(mutex& m)
  2. lock_guard(mutex& m, adopt_lock)

Among them mutex& mis the mutex, and the parameter adopt_lockindicates that it is assumed that the calling thread has obtained the ownership of the mutex and managed it, because it will be automatically locked when it is constructed, soadopt_lock其实就是告诉这个锁已经提前加过了。

I think of the automatic member variable lock written by Brother Yu

#include <iostream>
#include <mutex>
#include <vector>
#include <string>
#include <ctime>
#include <thread>

using namespace std;

// 时间模拟消息
string mock_msg()
{
	char buff[30] = { 0 };
	static int i = 100000;
	sprintf_s(buff, "%d", i--);
	return buff;
}

class CMutexTest
{
public:
	void recv_msg(); //接收消息
	void read_msg(); //处理消息
private:
	vector<string> msg_queue; //消息队列
	mutex m_mutex;	//互斥量
};

// 模拟接收消息
void CMutexTest::recv_msg()
{
	while (true)
	{
		string msg = mock_msg();
		cout << "recv the msg " << msg << endl;

		// 使用"{ }"限定lock_guard作用域
		{
			lock_guard<mutex> mylockguard(m_mutex);	
			// 消息添加到队列
			msg_queue.push_back(msg);
		}
		this_thread::sleep_for(chrono::milliseconds(10));//方便观察数据
	}
}

// 模拟读取处理
void CMutexTest::read_msg()
{
	while (true)
	{
		// 已经加锁
		m_mutex.lock();
		// 传递所有权给lock_guard,并传入adopt_lock表示已获得所有权
		lock_guard<mutex> mylockguard(m_mutex, std::adopt_lock);
		if (!msg_queue.empty())
		{
			// 处理消息并移除
			string msg = msg_queue.front();
			cout << "read the msg " << msg << endl;
			msg_queue.erase(msg_queue.begin());
		}
		this_thread::sleep_for(chrono::milliseconds(15));//方便观察数据
	}
}

int main()
{
	CMutexTest my_test;
	thread recv_thread(&CMutexTest::recv_msg, &my_test); //接收线程
	thread read_thread(&CMutexTest::read_msg, &my_test); //处理线程

	recv_thread.join();
	read_thread.join();
}

unique_lock replaces lock_guard


unique_lock is a class template, in general, lock_guard (recommended); lock_guard replaces lock() and unlock() of mutex;

unique_lock is much more flexible than lock_guard, less efficient, and takes up more memory.
C++11 multi-threaded unique_lock detailed explanation_u012507022's blog-CSDN blog_c++ unique_lock

void inMsgRecvQueue()
	{
		for (int i = 0; i < 10000; i++)
		{
			cout << "inMsgRecvQueue()执行,插入一个元素" << i << endl;
			std::unique_lock<std::mutex> sbguard(my_mutex, std::defer_lock);//没有加锁的my_mutex
			sbguard.lock();//咱们不用自己unlock
			//处理共享代码
 
		    //因为有一些非共享代码要处理
			sbguard.unlock();
			//处理非共享代码要处理。。。
 
			sbguard.lock();
			//处理共享代码
 
			msgRecvQueue.push_back(i);
			//...
			//其他处理代码
			sbguard.unlock();//画蛇添足,但也可以
		}
	}

Unique_lock ownership transfer
std::unique_lock<std::mutex> sbguard(my_mutex);//ownership concept

sbguard has the ownership of my_mutex; sbguard can transfer its ownership of mutex (my_mutex) to other unique_lock objects;

Therefore, the ownership of the mutex of the unique_lock object can be transferred, but it cannot be copied.

方法1 :std::move()

方法2:return std:: unique_lock<std::mutex>  代码如下:

std::unique_lock<std::mutex> sbguard2(std::move(sbguard));//移动语义,现在先当与sbguard2与my_mutex绑定到一起了
 
//现在sbguard1指向空,sbguard2指向了my_mutex


std::unique_lock<std::mutex> rtn_unique_lock()
	{
		std::unique_lock<std::mutex> tmpguard(my_mutex);
		return tmpguard;//从函数中返回一个局部的unique_lock对象是可以的。三章十四节讲解过移动构造函数。
		//返回这种举报对象tmpguard会导致系统生成临时unique_lock对象,并调用unique_lock的移动构造函数
	}
 
	void inMsgRecvQueue()
	{
		for (int i = 0; i < 10000; i++)
		{
			std::unique_lock<std::mutex> sbguard1 = rtn_unique_lock();
 
			msgRecvQueue.push_back(i);
		}
	}

To sum up, lock_guard is used with adopt_lock, and unique_lock is used with defer_lock. When both can be used, lock_guard is recommended because it is faster and uses less memory space. unique_lock supports the transfer of ownership, so it is more flexible.
————————————————
Copyright statement: This article is an original article of CSDN blogger "u012507022", following the CC 4.0 BY-SA copyright agreement, please attach the original source link and this statement for reprinting .
Original link: https://blog.csdn.net/u012507022/article/details/85909567

condition_variable

When  std::condition_variablea function of the object wait is called, it uses  std::unique_lock(passes  std::mutex) to lock the current thread. The current thread will be blocked until another thread  std::condition_variable calls  notification a function on the same object to wake up the current thread.

std::condition_variable Objects are usually used  std::unique_lock to wait. If you need to use another  lockable type, you can use std::condition_variable_anya class.  std::condition_variable_any The usage will be mentioned later in this article.

Introduction to std::condition_variable::notify_one()

Wake up a waiting( wait) thread. If there are no waiting threads, this function does nothing. If there are multiple waiting threads at the same time, it is undefined to wake up a thread (unspecified).

Introduction to std::condition_variable_any

Similar to  std::condition_variable, except std::condition_variable_anythat  wait functions can take any  lockablearguments, but  std::condition_variableonly  std::unique_lockarguments of type , and are otherwise std::condition_variablealmost identical.

temporary thread

C++11 began to support multi-threaded programming. Previously, multi-threaded programming required system support. Creating threads under different systems requires different APIs such as pthread_create(), Createthread(), beginthread(), etc., which are more complicated to use. , C++11 provides new header files <thread>, <mutex>, <atomic>, <future>, etc. to support multithreading

int main()

{

    std::vector<std::thread> threads;
    for(int i = 0; i < 5; ++i){

        threads.push_back(std::thread([](){

            std::cout << "Hello from lamda thread " << std::this_thread::get_id() << std::endl;

        }));

    }

  C++11 supports Lambda expressions, so the callback function of a new thread can also be in the form of a Lambda expression, but note that if you use Lambda expressions, it is best not to use the reference method, you should use the value transfer method to access Data, using references in multiple threads can easily cause confusion. If you use reference parameters, it is best to detach the thread.

 Summary
(a) If you pass a simple type such as int, it is recommended to pass by value instead of using references to prevent complications.
(b) If you pass class objects, avoid implicit type conversion. All create a temporary object in the line of creating a thread, and then connect it with a reference in the function parameter, otherwise the system will build an object (
c) Final conclusion: It is recommended not to use detach(), only use join() , so that there is no problem of invalid references to memory caused by local variables

shared_ptr<thread> thrd(new thread([this](){ std::this_thread::sleep_for(std::chrono::seconds(2);
print("dosomething"))}))


————————————————
Copyright statement: This article is an original article of CSDN blogger "Scarlett2025", following the CC 4.0 BY-SA copyright agreement, please attach the original source link and this statement for reprinting .
Original link: https://blog.csdn.net/Scarlett2025/article/details/123011038

 Introduction to DllMain


Just like exe has a main or WinMain entry function, a DLL also has an entry function, which is DllMain. Use "DllMain" as the keyword to see how the MSDN help document introduces this function.
The DllMain function is an optional method of entry into a dynamic-link library (DLL). (Brief translation: For a Dll module, the DllMain function is optional.) This sentence is very important. Many beginners may think that a dynamic link library must have a DllMain function. In fact, like many DLLs that only contain resource information, there is no DllMain function.
1.2 When to call DllMain
       When does the system call the DllMain function? Both LoadLibrary and FreeLibrary will call the DllMain function during static linking or dynamic linking. The third parameter fdwReason of DllMain specifies the reason for the system to call Dll, which may be DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH, DLL_THREAD_ATTACH, and DLL_THREAD_DETACH. Let's analyze when the system calls DllMain from these four situations.             
1.2.1 DLL_PROCESS_ATTACH
       We all know that if a program wants to call a function in a Dll, it must first map the DLL file to the address space of the process. To map a DLL file to the address space of a process, there are two methods: static link and dynamic link LoadLibrary or LoadLibraryEx.
       When a DLL file is mapped to the address space of the process, the system calls the DllMain function of the DLL, and the passed fdwReason parameter is DLL_PROCESS_ATTACH. This call will only happen for the first mapping. If the same process calls LoadLibrary or LoadLibraryEx again for the DLL that has been mapped in, the operating system will only increase the number of times the DLL is used, and it will not call the DllMain function of the DLL with DLL_PROCESS_ATTACH. When different processes use the same LoadLibrary DLL, the first mapping of each process will use DLL_PROCESS_ATTACH to call the DllMain function of the DLL.
       You can refer to the DLL_PROCESS_ATTACH_Test function of DllMainTest
—————————————————
Copyright Notice: This article is an original article by CSDN blogger "Xu Zhenping", following the CC 4.0 BY-SA copyright agreement, please attach the reprint Link to the original source and this statement.
Original link: https://blog.csdn.net/benkaoya/article/details/2504781

Guess you like

Origin blog.csdn.net/baidu_39486224/article/details/124748991