注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

C++11及BOOST特性之一nocopyable,pthread_once和call_once  

2013-12-04 21:33:18|  分类: C++(VC)编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

C++11BOOST特性之一nocopyablepthread_oncecall_once

C++11已经到了,C++14也在招手,得赶紧学,C++11是有不少新特性的,但BOOST里的未必就是了,只是为了考虑到C++11就都叫新特性了。

先讲一个nocopyable,这个特性在创建单实例方面很有帮助。

一、在陈硕的博客里,有这样一段代码:

#include <pthread.h>

template<typename T>

class Singleton : boost::noncopyable

{

 public:

  static T& instance()

  {

    pthread_once(&ponce_, &Singleton::init);

    return *value_;

  }

  static void init()

  {

    value_ = new T();

  }

 

 private:

  static pthread_once_t ponce_;

  static T* value_;

};

template<typename T>

pthread_once_t Singleton<T>::ponce_ = PTHREAD_ONCE_INIT;

template<typename T>

 

T* Singleton<T>::value_ = NULL;

 

上面这个 Singleton 没有任何花哨的技巧,用 pthread_once_t 来保证 lazy-initialization 的线程安全。使用方法也很简单:

Foo& foo = Singleton<Foo>::instance();

这种方法即使乱序执行的情况下,不使用eager initialize、或者动用 memory barrier (内存栅栏)这样的大杀器也能达到单实例的效果。

二、然后再看一个自己写的,这个可以防止多次实例化:

class noncopyable 

protected: 

    noncopyable (void) 

    { 

    } 

    ~noncopyable (void) 

    { 

 

    } 

 

private:  // emphasize the following members are private 

    noncopyable (const noncopyable&); 

    const noncopyable& operator= (const noncopyable&); 

};

使用方法:

class Test public noncopyable

{

};

 

void main()

{

   Test a,c;

   Test b(a);  ///<------1 error

 

   c = a;     ///<------(2) error

}

三、当然还有下面BOOST中的这种情况:

#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED 

#define BOOST_NONCOPYABLE_HPP_INCLUDED 

 

namespace boost { 

 

//  Private copy constructor and copy assignment ensure classes derived from 

//  class noncopyable cannot be copied. 

 

//  Contributed by Dave Abrahams 

 

namespace noncopyable_  // protection from unintended ADL 

  class noncopyable 

  { 

   protected: 

      noncopyable() {} 

      ~noncopyable() {} 

   private:  // emphasize the following members are private 

      noncopyable( const noncopyable& ); 

      const noncopyable& operator=( const noncopyable& ); 

  }; 

 

typedef noncopyable_::noncopyable noncopyable; 

 

} // namespace boost 

 

#endif  // BOOST_NONCOPYABLE_HPP_INCLUDED 

示例:

#include "tfun.h" 

 

class myclass: public boost::noncopyable 

public: 

    myclass(){}; 

    myclass(int i){}; 

}; 

 

int main() 

    myclass cl1(); 

    myclass cl2(1); 

 

    // myclass cl3(cl1);    // error 

    // myclass cl4(cl2);    // error 

 

    return 0; 

看看二和三没有什么区别吧。

在一中,用到了pthread_once,可以保证函数 执行一次,而在C++11中有一个类似的函数,叫做call_once,这个同样也可以保证函数只执行一次。但是要注意,在设定初始状态时,一定要设置为0,否则其运行的结果不可知。(pthread_once状态可设置为三种,012)。

可以参考http://blog.csdn.net/ixidof/article/details/6645269

Call_once的例程:

#include <iostream>

#include <thread>

#include <mutex>

 

std::once_flag flag;

 

void do_once()

{

    std::call_once(flag, [](){ std::cout << "Called once" << std::endl; });

}

 

int main()

{

    std::thread t1(do_once);

    std::thread t2(do_once);

    std::thread t3(do_once);

    std::thread t4(do_once);

 

    t1.join();

    t2.join();

    t3.join();

    t4.join();

}

运行结果:called_once

#include <iostream>

#include <thread>

#include <mutex>

 

std::once_flag flag;

 

inline void may_throw_function(bool do_throw)

{

  // only one instance of this function can be run simultaneously

  if (do_throw) {

    std::cout << "throw\n"; // this message may be printed from 0 to 3 times

    // if function exits via exception, another function selected

    throw std::exception();

  }

 

  std::cout << "once\n"; // printed exactly once, it's guaranteed that

      // there are no messages after it

}

 

inline void do_once(bool do_throw)

{

  try {

    std::call_once(flag, may_throw_function, do_throw);

  }

  catch (...) {

  }

}

 

int main()

{

    std::thread t1(do_once, true);

    std::thread t2(do_once, true);

    std::thread t3(do_once, false);

    std::thread t4(do_once, true);

 

    t1.join();

    t2.join();

    t3.join();

    t4.join();

}

运行结果:

throw

throw

once

上面这两个例程是用GCC4.8编译的。大家注意。

支持C++11的编译器肯定会越来越多,大家快幸福了。

  评论这张
 
阅读(3003)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017