boost::call_once应用及其实现

 

以下是一个典型的运用call_once实现一次初始化的例子:

 1 #include <boost/thread/thread.hpp>
 2 #include <boost/thread/once.hpp>
 3 #include <iostream>
 4 
 5 int i = 0;
 6 int j = 0;
 7 boost::once_flag flag = BOOST_ONCE_INIT;
 8 
 9 void init()
10 {
11     ++i;
12 }
13 
14 void thread()
15 {
16     boost::call_once(&init, flag);
17     ++j;
18 }
19 
20 int main(int argc, char* argv[])
21 {
22     boost::thread thrd1(&thread);
23     boost::thread thrd2(&thread);
24     thrd1.join();
25     thrd2.join();
26 
27     std::cout << i << std::endl;
28     std::cout << j << std::endl;
29 
30     return 0;
31 }
结果显示,全局变量i仅被执行了一次++操作,而变量j则在两个线程中均执行了++操作。

 

原理:

    利用传入的 flag的地址和current process id 为变量来构造一个字符串, 并用此字符串构造一个named mutex,
使得此mutex在同一进程内,相对同个flag唯一.第一次获得此mutex所有权的线程执行传入的函数对象, 并将flag修改为特定的值,
其他线程判断flag是否被修改到这个特定的值, 如果修改了则不调用函数直接跳过. 采用双判断机制来减少调用waitforsingleobject的次数,提高效率

关键原码:

 

void call_once(once_flag& flag,Function f)
    {
        // Try for a quick win: if the procedure has already been called
        // just skip through:
        long const function_complete_flag_value=0xc15730e2; //
第一次完成call后将flag值修改为此值

       
if(::boost::detail::interlocked_read_acquire(&flag)!=function_complete_flag_value)//
第一次判断,可以减少waitforsingleobject次数
        {
            void* const
mutex_handle(::boost::detail::create_once_mutex(&flag));//创建进程内唯一的metux
            BOOST_ASSERT(mutex_handle);
            detail::win32::handle_manager const closer(mutex_handle); //handle
guard, 离开作用域自动closehandle
            detail::win32_mutex_scoped_lock const lock(mutex_handle); //mutex
guard, 构造函数中waitforsingleobject(传入的mutex handle),离开作用域自动releaseMutex
       
            if(flag!=function_complete_flag_value)//
第二次判断,waitforsingleobject后再次判断call是否已经调用
            {
                f();
               
BOOST_INTERLOCKED_EXCHANGE(&flag,function_complete_flag_value);//原子操作,给flag赋值
            }
        }
    }

 

 

技术
©2019-2020 Toolsou All rights reserved,
一个名叫“讨火车”的小村子 终于把火车讨来了运营商 网站访客手机号码抓取hive压缩&&hdfs合并小文件精准手机号抓取,运营商大数据函数基本定义和使用‘未完待续Spring Boot教程十六:SpringBoot注入类实现多线程基于神经网络的车辆牌照字符识别技术MyBatis 新增数据 成功 返回 自增主键ID值json反斜杠问题接错水管喝了三年软水?软水和软水机究竟有何用