Boost (一)
看了Boost才知道Boost原来如此强大,EOS用Boost果然是有原因的啊。
元函数:
元变成也称为“超编程”, 是一种泛型编程的一种,广义上讲,所有使用template 的泛型代码都可以称为元程序,因为只定义了代码的产生规则,是生成代码的模板。
元数据(Meta data) 在C++中是指编译期可操作的数据,是元编程的基础。
元数据可分为值型元数据(int,double等POD值类型)类元数据(class, struct等)
typedef 可以定义(声明)元数据。
typedef int meta_data1;
typedef std::vector<float> meta_data2;
元函数例子:
template <typename arg1, typename arg2, ...>
struct meta_function
{
typedef some-defined type;
static int const value = some-int;
}
元编程的好处:
1)在编译期运行,提高效率,一些错误在编译期发现而不是在链接和运行期间发现
2)采用template应用上非常简便,没有C++以前的overwrite,对于不同的类型都要写不同的构造和析构函数。这个主要是template的功能, STL的优点,但是Boost中又继续优化,使用起来变得轻便。
3)安全的智能指针(不再赘述)
type_traits:
6个检查复合类: is_arithmetic<T>, is_fundamental<T>, is_compound<T>, is_member_pointer<T>,
is_object<T>, is_scalar<T>
其他:是否有某个属性has_xxx, 状态,重载等检查,以及类型转换等
boost::thread 和boost::asio
C++中没有语言级别的并发支持,因而线程中的一些共享资源互斥功能的实现都需要每次去自己实现,Boost提供了两个编程组件: thread 库和 asio 库。 Thread库提供了可移植的线程处理,而asio 是用于同步和异步IO操作的功能库
Thread提供了其中互斥量类型(实际上只有吴忠):
mutex,
shared_mutex: multiple-reader/single-writer
timed_mutex: 超时锁定功能
recursive_timed_mutex: 递归式互斥
兼容类两种略
mutex 的内部声明中定义的常用功能;
class mutex: boost::noncoyable
{
public:
void lock();
bool try_lock();
void unlock();
bool timed_lock(system_time const& abs_time);
template<typename TimeDuration>
bool timed_lock(TimeDuration const& relative_time);
typedef unspecified-type scoped_lock;
typedef unspecified-type scoped_try_lock;
}
以上带try 是兼容版本
Thread库又提供了一系列RAII的lock_guard用于辅助锁定互斥量 (scoped_lock)
在构造时锁定互斥量,而在析构时自动解锁。
使用lock_guard 可以省略try-catch,比较下面两端代码:
不用lock_guard:
mutex mu;
try{
mu.lock();
cout << "some operations" << endl;
mu.unlock();
}
catch(...)
{
mu.unlock();
}
使用lock_guard:
mutex mu;
mutex::scoped_lock lock(mu);
cout << " some operations" << endl;
thread 类不能拷贝,但提供转移语义,因此构造thread 工厂类,封装细节,创建thread, thread 一旦被创建,就开始执行,没有start, begin 函数。
template<typename F>
thread make_thread(F f)
{
return thread(f);
}
一个使用thread对象的例子:
int main()
{
atom_int x; //计数器
thread(printing, ref(x), "hello");
thread(printing, ref(x), "boost");
this_thread::sleep( posix_time :: seconds(2)); // 等待2秒
}
最后一句 sleep()用于等待线程结束,否则会因为main() 的return 语句导致主线程结束,而子线程尚未运行则结束。
join(), timed_join() 可以判断是否标识了可执行的线程。
上例改为:
int main()
{
atom_int x; //计数器
thread t1(printing, ref(x), "hello");
thread t2(printing, ref(x), "boost");
t1.timed_join(posix_time::seconds(1)); t1等一秒后返回
t2.join(); //等t2结束再返回
}
detach标识thread 对象和thread 分离,即t1 或t2不代表任何线程,但线程仍然继续执行。
thread类还提供了几个有用的静态函数:
yield(): 指示线程放弃时间片,允许其他线程运行;
sleep(): 略 参数是system_time UTC 时间,不是时间长度
hardware_concurrency(): 可获得硬件系统可并行的线程数量,即CPU数
但是this_thread::sleep()使用的时间是时间长度
线程都是可以中断的,但Thread允许控制线程的中断,采用以下函数:
interruption_enabled(), interruption_requested(),
disable_interruption() 在其生命周期中不可中断,而restore_interruption()可以恢复到可中断状态。
interruption_point()
其他议题:
-
条件变量: 是thread的同步机制实现线程间通信,可以和互斥量配合使用。
例如: condition_variable_any,
使用方法是先用条件变量检查条件,不满足的话继续等待,满足的话调用notify_one, notify_all 通知其他线程。
(我估计在EOS的各个节点之间需要这种通讯机制,不过不知道用的是进程还是线程) -
future: 用于异步操作线程返回值,例如: packaged_task, unique_future 等。
future 使用packaged_task 和 promise 两个模板来包装异步调用。
unique_future和shared_future用于获取异步调用结果,也就是future值。
另:promise 只用于获取值,而不能获取函数 -
线程的本地存储(进行到一半时候的系统变量的存储)