YAML
ISO 8601
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
- header only
- high speed
- efficient serialization
- API similar to std::unordered_map and std::unordered_set
- 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_duration
because 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:
lock_guard(mutex& m)
lock_guard(mutex& m, adopt_lock)
Among them mutex& m
is the mutex, and the parameter adopt_lock
indicates 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_variable
a 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_any
a 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_any
that wait
functions can take any lockable
arguments, but std::condition_variable
only std::unique_lock
arguments of type , and are otherwise std::condition_variable
almost 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