0%
C++11#001#std:call_once

使用背景

在多线程编程环境中,我们有时希望某个操作只做一次,比如获取一些系统变量;或者某个函数只被调用一次。我们就可以采用系统提供的std::call_once来保证。

我们再看下call_once的定义:

1
2
template< class Callable, class... Args >
void call_once( std::once_flag& flag, Callable&& f, Args&&... args );

用法示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// 将文件保存为 call.cpp
// 编译:g++ -o test call.cpp -std=c++11 -pthread
// 运行:./test
#include <iostream>
#include <thread>
#include <mutex>
#include <sys/time.h>
#include <sys/resource.h>

int GetMaxOpenFileSys(struct rlimit *rlim)
{
// 获取最大文件描述符数量
::getrlimit(RLIMIT_NOFILE, rlim);

printf("GetMaxOpenFileSys Called\n");
}

int GetMaxOpenFile()
{
static std::once_flag once_flag;
static struct rlimit rlimit;

// 保证在多线程环境下,只调用GetMaxOpenFileSys一次
// 也就是说保证只调用::getrlimit一次
std::call_once(once_flag, GetMaxOpenFileSys, &rlimit);

return rlimit.rlim_max;
}

void ThreadEntry()
{
// 线程入口函数,我们先获取系统允许可打开的最多文件描述符数量
printf("MaxOpenFile:%d\n", GetMaxOpenFile());
}

int main(int argc, char ** argv)
{
std::thread xThreadA(ThreadEntry);
std::thread xThreadB(ThreadEntry);
std::thread xThreadC(ThreadEntry);
std::thread xThreadD(ThreadEntry);

xThreadA.join();
xThreadB.join();
xThreadC.join();
xThreadD.join();

return 0;
}

程序运行结果:

1
2
3
4
5
6
motadou@dev-0-0:/home/motadou/objs/test$ ./test 
GetMaxOpenFileSys Called
MaxOpenFile:4096
MaxOpenFile:4096
MaxOpenFile:4096
MaxOpenFile:4096

从上面的运行结果,我们就可以看到程序在多线程环境中,只调用了GetMaxOpenFileSys()一次。