您的位置:首页 > 编程语言 > C语言/C++

C++11 once_flag与call_once组合,实现函数只调用一次

2019-01-28 20:57 3403 查看
版权声明:转载请注明出处!! https://blog.csdn.net/xucongyoushan/article/details/86500367

once_flag与call_once

头文件

#include <mutex>

once_flag结构

std::once_flag实例的状态,指示所关联的函数尚未被调用。
其构造函数拥有constexpr指定符,以带有静态存储时间段的实例,作为静态初始化阶段的一部分被构造,避免竞争条件和初始化顺序问题。

struct once_flag
{
constexpr once_flag() noexcept : _Opaque(0){}
once_flag(const once_flag&) = delete;
once_flag& operator=(const coce_flag&) = delete;
void *_Opaque;
}

call_once函数模板

在同一std::once_flag对象上,std::call_once调用被序列化。
当且仅当_Fx的调用返回而无异常,std::call_once的调用有效。
若在同一std::once_flag对象上,之前未有过有效的std::call_once调用,参数_Fx(或其副本)如同通过INVOKE(_Fx, _Ax)一样被调用。
如果在同一std::once_flag对象上,之前有过有效的std::call_once,对std::call_once的后续调用直接返回而不执行_Fx。

template<typename _Fn, typename... _Args>
inline void call_once(once_flag& _Flag, _Fn&& _Fx, _Args&&... _Ax);

用法

有时对于一类对象,只需初始化一次环境,可以采用类似的封装方式:

#include <mutex>
class Module
{
public:
Module() {}
~Module() {}
void init()
{
static std::once_flag once_init;
std::call_once(once_init, openLibs);
}
private:
static void openLibs() {}
};

错误用法

在上述的openLibs函数中,再次间接通过std::call_once调用自己,会导致栈溢出错误。这是由于未完成一次有效调用,还未改变std::once_flag的状态,仍然造成openLibs被多次调用的情况。

参考文献

C++并发编程实战

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: