1、BOOST 应用初探作者:冯刚2011-8-41 背景BOOST 是由 c+标准化委员会成员参与开发的 c+标准的准官方库,他是 C+标准库的发动机。下一代 C+标准 C+0x 的标准库很多来自于 boost。Boost 库覆盖了广泛的领域,从数学库到智能指针,从模板元编程库到预处理器库及语法词法分析,从线程到 lambda 表达式,等等。所有 Boost 库都具有宽松的许可证,确保库可以被自由使用于商用软件。2 功能2.1概况Boost 库涵盖了很广泛的领域,下面就常用的功能像智能指针,正则表达式,函数对象bind 和 function, 线程和线程池,时间日期,多索引容器,哈希容器,bim
2、ap,日志,内存池,模板元编程,循环缓冲区,tuple, 观察者模式 signal2,网络通讯 asio 做一些介绍。2.2功能2.2.1 智能指针2.2.1.1 概论smart pointers(智能指针)是存储“指向动态分配(在堆上)的对象的指针”的对象。他们的行为很像 C+ 的内建指针,只是它们可以在适当的时候自动删除它们所指向的对象。智能指针在面对异常时有非常显著的作用,它们可以确保动态分配对象的完全析构。它们还可以用于跟踪多主人共享的动态分配对象。在概念上,智能指针可以看作拥有它所指向的对象,并因此在对象不再需要时负责将它删除。智能指针库提供了六个智能指针类模板:scoped_ptr
3、 简单的单一对象的唯一所有权。不可拷贝。scoped_array 简单的数组的唯一所有权。不可拷贝。shared_ptr 在多个指针间共享的对象所有权。shared_array 在多个指针间共享的数组所有权。weak_ptr 一个属于 shared_ptr 的对象的无所有权的观察者。intrusive_ptr 带有一个侵入式引用计数的对象的共享所有权。这些模板被设计用来补充 std:auto_ptr 模板的不足。2.2.1.2 智能指针 shared_ptrshared_ptr 类模板存储一个指向动态分配对象(一般是用 C+ new-expression 生成的)的指针。在最后一个 share
4、d_ptr 所指向的对象被销毁或重置时,要保证它所指向的对象被删除。每一个 shared_ptr 都符合 C+ 标准库的 CopyConstructible 和 Assignable 的必要条件,并因此能够用于标准库容器。因为提供了比较操作,因此 shared_ptr 可以和标准库中的关联式容器一起工作。通常,一个 shared_ptr 不能正确地持有一个指向动态分配的数组的指针。关于那种用法请参见 shared_array。因为在实现中使用了引用计数,shared_ptr 实例的循环引用不会被回收。例如,如果 main() 持有一个指向 A 的 shared_ptr, A 又直接或间接持有一
5、个指回 A 的 shared_ptr,A 的使用计数是 2。最初的 shared_ptr 析构后将导致一个使用计数为 1 的 A 被悬挂。使用 weak_ptr 以“打破循环”。这个类模板被 T 参数化,T 是被指向的对象的类型。shared_ptr 和它的大多数成员函数对于 T 没什么要求,允许它是一个不完整类型,或者为 void。对 T 有附加要求的成员函数 (constructors, reset) 都明确地记录在下面。只要 T* 能被隐式地转换到 U*,则 shared_ptr 就能被隐式地转换到 shared_ptr。特别是,shared_ptr 隐式转换到 shared_ptr,当
6、 U 是 T 的一个可访问基类的时候,还能转换到 shared_ptr,以及转换到 shared_ptr。惯用手法由于智能指针是线程安全的,建议在代码里只为一个对象生成单一的shared_ptr,在多线程环境中传递参数时使用 weak_ptr,这样当 shared_ptr 被析构,weak_ptr 也会得到通知,变为无效,这样可以有效地防止野指针,同时也防止了潜在的循环引用,无法释放对象的问题。shared_ptr spA = shared_ptr(new A);int func(weak_ptr wpA)If(!wpA.expired())/正常处理逻辑shared_ptr spA = wp
7、A.lock();/Use spAelse/智能指针已被其他线程释放func(spA);2.2.1.3 智能指针 weak_ptr简介weak_ptr 是 Boost 智能指针 shared_ptr 的一个重要伙伴。它允许打破循环依赖。另外,它还可以处理一个非常常见的问题悬空指针。当销毁最后一个智能指针 shared_ptr,它会释放掉共享的资源。通过使用智能指针 weak_ptr,这方面的信息会传播给所有观察该共享资源的智能指针 weak_ptr,通过 weak_ptr可以知道该共享资源已经释放,这意味着不会发生无意间访问无效指针的情形。这就是观察者模式的一个特例,也就是说,当销毁资源的时候
8、,就会通知所有对资源感兴趣的 weak_ptr,通过调用 weak_ptr.expired(),当返回值为 true 时,就表示该共享资源已经释放了。weak_ptr 类模板存储一个引向已被 shared_ptr 管理的对象的 “weak reference“(弱引用)。为了访问这个对象,一个 weak_ptr 可以利用 shared_ptr 的构造函数或成员函数 lock 转换为 shared_ptr。当最后一个指向对象的 shared_ptr 消失,而对象也被删除后,从一个引向已被删除对象的 weak_ptr 实例获取 shared_ptr 的企图就会失败:构造函数会抛出一个 boost:
9、bad_weak_ptr 类型的异常,而 weak_ptr:lock 会返回一个 empty shared_ptr。每一个 weak_ptr 都符合 C+ 标准库的 CopyConstructible 和 Assignable 的必要条件,并因此能够用于标准库容器。因为提供了比较操作,因此 weak_ptr 可以和标准库中的关联式容器一起工作。weak_ptr 的操作绝不会抛出异常。这个类模板被 T 参数化,T 是被指向的对象的类型。相对于 shared_ptr,weak_ptr 提供了一个非常有限的操作子集,因为在多线程程序中访问它所存储的指针是非常危险的,甚至有时在一个单线程程序中也是不安
10、全的(也就是说,它可能引起未定义行为)。姑且假设 weak_ptr 有一个返回 raw pointer(裸指针)的 get 成员函数,考虑下面这个无辜的代码片段:shared_ptr p(new int(5);weak_ptr q(p);/ some time laterif(int * r = q.get()/ use *r设想在 if 之后,但是又恰恰在 r 被使用之前,另一个线程执行了语句 p.reset()。这样 r 就成了一个 dangling pointer(悬挂指针)。解决这个问题的方案是从 q 创建一个临时的 shared_ptr:shared_ptr p(new int(5)
11、;weak_ptr q(p);/ some time laterif(shared_ptr r = q.lock()/ use *r这样,r 就持有一个引向 q 所指向的对象的引用。即使在其它线程中执行了 p.reset(),那个对象也会继续活着,直到 r 离开作用域或者被 reset。通过获得一个指向这个对象的 shared_ptr,我们可以有效地保住它不被析构。2.2.2 正则表达式xpressive 是一个先进的、面向对象的、用于 C+的正则表达式模板库。正则表达式可以以字符串方式编写并在运行期分析,也可以以表达式模板方式编写并在编译期分析。正则表达式可以相互引用,或者递归引用其本身,你
12、就可以用它们来构建任意复杂的语法。它与 Boost.Regex 库的区别就是无需编译,全模板库。如果你要在 C+中处理文本,通常你有两个不相交的选项:正则表达式引擎或语法分析生成器。正则表达式引擎(如 Boost.Regex)更为强大和灵活;文本的模式以字符串方式表示,可以在运行期指定。但是,这意味着语法错误同样要到运行期才能被检测。另外,正则表达式不适合于高级的文本处理任务,如匹配平衡的、嵌套的标签。那些任务传统上都是由语法分析生成器(如 Spirit 语法分析器框架)来处理的。这些工具更为强大,但不够灵活。它们通常不允许你随时随意地修改你的语法规则。此外,它们不具备正则表达式的完全回溯语义
13、,对于某些类型的模式来说,这样对作者更具有挑战性。将这两种方法无缝地集合到一起,在 C+的文本处理世界中占据了独特的优势。通过 xpressive,你可以选择更象使用 Boost.Regex 那样去使用它,将正则表达式表示为字符串。或者你也可以象使用 Spirit 那样使用它,将你的 regexes 写为 C+表达式,获得一种专用于文本处理的嵌入式语言所带来的所有好处。更重要的是,你可以混用这两种方式,从而获得两者的好处,对于那些要静态绑定的正则表达式编写正则表达式 语法 - 由编译器进行硬编码和语法检查 - 其它的则动态绑定并在运行期指定。这些正则表达式可以相互递归地引用,在以前的正则表达式
14、不能进行模式匹配的字符串中进行模式匹配。Xpressive 是一个只含头文件的模板库,这意味着你不需要修改你的构建脚本或链接任何独立的 lib 文件就可以使用它。你所要做的就是 #include 。如果你只使用静态 regexes,你可以只包含 xpressive_static.hpp 以提高编译速度。同样,如果你计划只使用动态regexes,则可以只包含 xpressive_dynamic.hpp。表 28.1. xpressive 的工具箱Tool 工具 Description 说明 basic_regex 是 xpressive 之中最重要的类型。你用 xpressive 做的任何事情都
15、要从创建一个类型为 basic_regex, sub_match 含有 regex_match() 或 regex_search() 操作的结果。它就象一个存有 sub_match 对象含有一个已标记的子表达式(在 Perl 中又称为后向引用)。基本上,它只是一个迭代器对,代表了已标记子表达式的开始和结束。 regex_match() 检查一个字符串是否匹配一个regex。 regex_match() 要成功,必须是 整个字符串 从头到尾匹配 regex。如果你给了 regex_match() 一个 match_results,那么它会将所有找到的带标记子表达式写入其中。 regex_repl
16、ace() 给定一个输入字符串,一个 regex 和一个替代字符串,regex_replace() 通过将输入字符串中与 regex 相匹配的部分替换为替代字符串来构建一个新的字符串。替代字符串可以含有对带标记子表达式的引用。 regex_iterator 会返Tool 工具 Description 说明 回一个 match_results 可以找出下一个匹配。 regex_token_iterator,除了一点,解引用一个 regex_token_iterator 一个用于 basic_regex,因为 basic_regex。不过,如果你需要做一些花哨的东西,如创建一个带有不同 std:l
17、ocale 的 basic_regex 了。 现在你应该对 xpressive 所提供的工具有了一些了解,你可以通过回答以下两个问题来找到合适的工具: 1. 你要用哪种类型的迭代器来遍历你的数据? 2. 你要对你的数据做什么操作? 弄明白你的迭代器类型 在 xpressive 中的多数类都是根据迭代器类型参数化的模板类。xpressive 定义了一些常用的 typedefs 来让你可以更容易地选择合适的类型。你可以用下表基于你的迭代器类型来找到正确的类型。 下表 为 xpressive Typedefs 与迭代器类型std:string:const_iterator char const *
18、std:wstring:const_iterator wchar_t const * basic_rege sregex cregex wsregex wcregex std:string:const_iterator char const * std:wstring:const_iterator wchar_t const * x smatch cmatch wsmatch wcmatch regex_compiler sregex_iterator cregex_iterator wsregex_iterator wcregex_iterator regex_token_iterator
19、(delim= (set= /,-) / 后跟一个分隔符. (day= repeat(_d) delim / 和一个日期再跟一个分隔符. (year= repeat(_d _d); /和年份。cmatch what;if( regex_search( str, what, date ) )std:cout #include using namespace boost:xpressive;int main()std:string str( “I was born on 5/30/1973 at 7am.“ );/ 基本上与上一个例子中的 regex 相同,但用的是动态 regexsregex d
20、ate = sregex:compile( “(d1,2)(/-)(d1,2)2(?:d2)1,2)“ );/ 和在 Perl 中一样,$str = regex_replace( str, date, format );std:cout 5/30/1973 at 7am.查找匹配某个 regex 的所有子串并每次一个地分步处理它们 以下程序在一个宽字符串中查找单词。它使用 wsregex_iterator。注意,对 wsregex_iterator 的解引用将产生一个 wsmatch 对象。 #include #include using namespace boost:xpressive;i
21、nt main()std:wstring str( L“This is his face.“ );/查找一个完整的单词wsregex token = +alnum;wsregex_iterator cur( str.begin(), str.end(), token );wsregex_iterator end;for( ; cur != end; +cur )wsmatch const std:wcout . #include #include using namespace boost:xpressive;int main()std:string str( “Eric: 4:40, Kar
22、l: 3:35, Francesca: 2:32“ );/查找比赛时间sregex time = sregex:compile( “(d):(dd)“ );/ 对于每个匹配,记号迭代器首先取出第一个被标记的子表达式的值,然后是第二个子表达式的值int const subs = 1, 2 ;sregex_token_iterator cur( str.begin(), str.end(), time, subs );sregex_token_iterator end;for( ; cur != end; +cur )std:cout 返回字符串中不匹配该 regex 的其余部分。 #includ
23、e #include using namespace boost:xpressive;int main()std:string str( “Now is the time for all good men to come to the aid of their country.“ );/ find a HTML tag 查找一个 HTML 标签sregex html = optional(/) +_w ;/ 以下的 -1 指示记号迭代器显示字符串中不匹配正则表达式的部分。sregex_token_iterator cur( str.begin(), str.end(), html, -1 );
24、sregex_token_iterator end;for( ; cur != end; +cur )std:cout void operator ()( match_results const char_type space_ch = char_type( );std:fill_n( std:ostream_iterator( std:cout ), tabs_ * 4, space_ch );/输出匹配结果std:cout (f, _1, _1)(x); / f(x, x), i.e. zero有些编译器遇到 bind(f, .) 语法会发生问题。出于可移植性的原因,一种和上面的意思相同的
25、可选的表达方式也被支持:boost:bind(boost:type(), f, _1, _1)(x);但是要注意,这种可选语法只是作为一个 workaround 提供。它不是接口的一部分。当函数对象暴露了一个名为 result_type 的内嵌类型时,显式返回类型可以被省略:int x = 8;bind(std:less(), _1, 9)(x); / x (mem_fn(;X x;shared_ptr p(new X);int i = 5;bind( / x.f(i)bind( /( / (internal copy of x).f(i)bind( / (internal copy of p
26、)-f(i)最后两个示例的有趣之处在于它们生成“自包含”的函数对象。bind( / f(g(x)当函数对象被调用的时候,如果没有指定顺序,内部 bind 表达式先于外部 bind 表达式被求值,在外部 bind 表达式被求值的时候,用内部表达式的求值结果取代它们的占位符的位置。在上面的示例中,当用参数列表 (x) 调用那个函数对象的时候,bind(g, _1)(x) 首先被求值,生成 g(x),然后 bind(f, g(x)(x) 被求值,生成最终结果 f(g(x)。bind 的这个特性可被用来执行函数组合。参见示例 bind_as_compose.cpp,示范如何用 bind 达到与 Boo
27、st.Compose 类似的功能。注意第一个参数被绑定函数对象是不被求值的,即使它是一个由 bind 生成的函数对象或一个占位符参数,所以下面的示例不会如你所愿地工作:typedef void (*pf)(int);std:vector v;std:for_each(v.begin(), v.end(), bind(_1, 5);你所要的效果,可以通过将一个辅助函数对象 apply 用作它的第一个参数而获得,作为一个函数对象,它可以支撑它的参数列表。为了方便起见,在 boost/bind/apply.hpp 头文件中提供了一个 apply 的实现。下面是一个前面的示例的修改版本:typedef
28、 void (*pf)(int);std:vector v;std:for_each(v.begin(), v.end(), bind(apply(), _1, 5);尽管在缺省情况下,第一个参数是不被求值的,而所有其它参数被求值。但有时候不需要对第一个参数之后的其它参数求值,甚至当它们是内嵌 bind 子表达式的时候也不需要。这可以由另一个函数对象 protect 来帮助做到,它将类型掩饰起来,让 bind 无法对它进行识别和求值。在被调用的时候,protect 只是简单地不加更改地将参数列表转送到其它函数对象中。头文件 boost/bind/protect.hpp 包含一个 protect
29、 的实现。要在求值中保护一个 bind 函数对象,使用 protect(bind(f, .)。(重载的操作符(Boost 1.33 新增) )为了方便起见,由 bind 生成的函数对象重载了 logical not(逻辑非)操作符 ! 和关系操作符 =, !=, , =, / remove invisible objects以及方便地将 bind 的结果和一个值进行比较:std:find_if( first, last, bind( std:find_if( first, last, bind( 和一个占位符进行比较:bind( ;class playerpublic:void play();
30、void stop();button playButton, stopButton;player thePlayer;void connect()playButton.onClick = boost:bind(stopButton.onClick = boost:bind(2.2.4 线程库2.2.4.1 线程管理2.2.4.1.1 创建线程Class ParamInt value;Shared_ptr spParam = new shared_ptr (new Param);Class AInt Run(weak_ptr param);Shared_ptr spA = new shared_
31、ptr (new A);boost:shared_ptr thread(new boost:thread(boost:bind(2.2.4.1.2 等待线程退出thread-join();boost:system_time xt=delay(3);bool const joined= thread-timed_join(xt);thread -timed_join(boost:posix_time:seconds(3);2.2.4.1.3 线程中断thread -interrupt();2.2.4.1.4 线程休眠boost:this_thread:sleep(boost:posix_time
32、:milliseconds(10);2.2.4.1.5 获取线程 IDthread:id get_id() const;返回值: 如果*this 标识一个线程执行体, 返回有效线程标识( boost:thread:id。 否则返回空的线程标识(default-constructed boost:thread:id)。 抛出: 无 thread-get_id();2.2.4.1.6 线程退出的处理void exit_func(int exitcode)boost:this_thread:at_thread_exit(boost:bind(exit_func,0);2.2.4.2 线程池 线程池的
33、种类 先进先出队列线程池typedef thread_pool fifo_pool; 后进先出队列线程池typedef thread_pool lifo_pool; 优先级队列线程池typedef thread_pool prio_pool; 示例typedef fifo_pool pool;/创建线程池boost:threadpool:pool pool;pool.size_controller().resize(10);/调度线程池/这样调度boost:threadpool:future fut = boost:threadpool:schedule(pool,boost:bind(fun
34、c,1);或者这样调度pool.schedule(boost:bind(func,err);或那样调度packaged_task pfunc(boost:bind(func,1);Unique_future uf = pfunc.get_future();pool.schedule(boost:move(pfunc);packaged_task pfunc1(boost:bind(func,1);Unique_future uf1 = pfunc.get_future();pool.schedule(boost:move(pfunc1);wait_for_all(uf, uf1);coutwa
35、it();或者定时等待boost:xtime xt;boost:xtime_get(xt.sec += 30;xt.nsec += ns;io_ fut .timed_wait(xt);2.2.4.3 同步处理2.2.4.3.1 互斥量互斥量对象简化了线程间数据竟态保护和数据同步。一个线程通过一个锁定函数取得一个互斥量的所有权,通过一个对应的解锁函数释放所有权。互斥量可以是支持递归所有权的或非递归所有权的, 也可以同时属于多个线程。 Boost.Thread 库提供递归和非递归互斥量, 支持排他型的所有权和共享所有权(multiple-reader / single-writer)。 所有权概
36、念Boost.Thread 库支持四种基本的所有权概念: Lockable, TimedLockable, SharedLockable 和 UpgradeLockable。每种互斥量依据自己的目标实现一种或多种概念。 Lockable 概念 void lock() bool try_lock() void unlock() 实现 Lockable 概念需要提供下面的成员函数 : void lock(); bool try_lock(); void unlock(); 通过 函数 lock()或函数 try_lock() 获取的所有权需要通过 unlock()来释放。 TimedLockabl
37、e 概念 TimedLockable concept 概念细化了 Lockable concept 概念,支持尝试获取所有权时超时放弃。 实现 TimedLockable concept 概念的类型除了需要实现 Lockable concept 概念。还需要提供下面的成员函数: bool timed_lock(boost:system_time const template bool timed_lock(DurationType const 通过 函数 timed_lock() 获取的所有权需要通过 unlock()来释放。 bool timed_lock(boost:system_time
38、 const bool try_lock_shared(); bool unlock_shared(); bool timed_lock_shared(boost:system_time const 通过 函数 lock_shared(), try_lock_shared() 或 timed_lock_shared() 获取的所有权需要通过 unlock_shared()来释放。 void lock_shared() 效果: 当前线程阻塞直到取得互斥量的共享所有权。 后置条件: 当前线程取得互斥量的共享所有权。 抛出: 如果出错抛出 boost:thread_resource_error 异常
39、。 bool try_lock_shared() 效果: 当前线程尝试取得该互斥量的共享所有权,线程不阻塞。 返回: 如果取得互斥量的共享所有权返回 true, 否则返回 false。 后置条件: 如果返回 true, 当前线程取得互斥量的共享所有权。 抛出: 如果出错抛出 boost:thread_resource_error 异常。 bool timed_lock_shared(boost:system_time const。 返回: 如果取得互斥量的共享所有权返回 true, 否则返回 false。 。 后置条件: 如果返回 true, 当前线程取得互斥量的共享所有权。 抛出: 如果出错
40、抛出 boost:thread_resource_error 异常。 void unlock_shared() 前置条件: 当前线程拥有互斥量的共享所有权。 效果: 释放当前线程拥有的互斥量共享所有权。 后置条件: 当前线程不在拥有该互斥量共享所有权。 抛出: 无 UpgradeLockable 概念 UpgradeLockable concept 是 SharedLockable concept 的细化,特点在于允许所有权升级到独占状态。这是对共享所有权支持的 multiple-reader / single-write 模型的一个扩展:一个线程可以拥有 upgradable ownersh
41、ip 而同时其他线程拥有共享所有权 该线程可以在任何时候试图升级其所有权为独占式所有,如果此时没有其他线程拥有共享所有权,升级立即完成, 该线程就会拥有独占所有权, 这个所有权需要通过 unlock()来释放, 就像这个所有权是通过 lock()取得一样。 如果该线程试图升级到独占所有时,其他线程拥有对应的共享所有权, 升级会失败,该线程阻塞直到其获得独占所有权。 UpgradeLockable concept 中的所有权也可以降级 : 独占式所有权可以降级为可升级所有权或者共享所有权,可升级所有权可以降级为一般共享所有权。 如果一个类型要实现 UpgradeLockable concept
42、概念,除了需要实现 SharedLockable concept 概念, 它还需要提供下面的成员函数: void lock_upgrade(); bool unlock_upgrade(); void unlock_upgrade_and_lock(); void unlock_and_lock_upgrade(); void unlock_upgrade_and_lock_shared(); 通过函数 lock_upgrade() 取得的所有权需要通过函数 unlock_upgrade()来释放 。如果所有权类型通过函数 unlock_xxx_and_lock_yyy()改变 , 所有权必须
43、通过新所有权对应的释放函数来释放。 void lock_upgrade() 效果: 当前线程阻塞直到它获得可升级所有权。 后置条件: 当前线程取得该对象的可升级所有权。 抛出: 如果出错抛出 boost:thread_resource_error 异常。 void unlock_upgrade() 前置条件: 当前线程拥有该对象的可升级所有权。 效果: 释放当前线程拥有的该对象的可升级所有权。 后置条件: 当前线程不在拥有该对象的可升级所有权。 抛出: 无 void unlock_upgrade_and_lock() 前置条件: 当前线程拥有该对象的可升级所有权。 效果: 当前线程自动释放拥有
44、的该对象可升级所有权,并试图取得该对象的独占所有权, 线程阻塞直到其获得独占所有权。 后置条件: 当前线程拥有该对象的独占所有权。 抛出: 无 void unlock_upgrade_and_lock_shared() 前置条件: 当前线程拥有该对象的可升级所有权。 效果: 当前线程自动释放拥有的该对象可升级所有权,取得共享所有权,该函数会立即返回。后置条件: 当前线程拥有该对象的共享所有权。 抛出: 无 void unlock_and_lock_upgrade() 前置条件: 当前线程拥有该对象的独占所有权。 。 效果: 当前线程自动释放拥有的该对象独占级所有权,取得可升级所有权,该函数会立
45、即返回。 后置条件: 当前线程自动拥有该对象可升级所有权。 抛出: 无 锁定类型(Lock Types) lock_guard unique_lock shared_lock upgrade_lock upgrade_to_unique_lock scoped_try_lock lock_guard lock_guard(Lockable lock_guard(Lockablelock_guard();boost:lock_guard 非常简单: 构造函数传入一个可锁定对象,构造函数取得可锁定对象的所有权。 析构时释放所有权。 这样为可锁定对象提供了一个 RAII 风格的外观, 方便实现异常安
46、全的锁定和解锁。 额外的, 构造函数 the lock_guard(Lockable const try_to_lock_t try_to_lock=;const adopt_lock_t adopt_lock=; unique_lock #include templateclass unique_lockpublic:unique_lock();explicit unique_lock(Lockableunique_lock(Lockableunique_lock(Lockableunique_lock(Lockableunique_lock(Lockableunique_lock();un
47、ique_lock(detail:thread_move_t other);unique_lock(detail:thread_move_t other);operator detail:thread_move_t ();detail:thread_move_t move();unique_lockunique_lockvoid swap(unique_lockvoid swap(detail:thread_move_t other);void lock();bool try_lock();templatebool timed_lock(TimeDuration constbool timed
48、_lock(:boost:system_time constvoid unlock();bool owns_lock() const;operator unspecified-bool-type() const;bool operator!() const;Lockable* mutex() const;Lockable* release();boost:unique_lock 比 boost:lock_guard 复杂许多: 不仅是它提供 RAII 风格的外观, 它也允许推迟获得锁定, 直到 lock() 函数显式调用, 或者支持非阻塞方式获得锁定, 或者是支持超时锁定。 最后, 析构函数在可锁定对象被其锁定的情况下调用 unlock() 函数。 boost:unique_lock 特化实现了 TimedLockable concept 概念(e.g. boost:unique_lock), 或者 Lockable concept 概念 (e.g. boost:unique_lock)。 如果函数 mutex() 返回指向的 m 指针并且 owns_lock() 返回 true,该boost:unique_lock 实例拥有一个可锁定对象的锁定状态 。如果该种实例被销毁, 析构函数会调用函数 mutex()-unlock()。 boost:unique_l