造轮子笔记-关于C++11的线程库

在2016年最后的几天里,我尝试以muduo/master为蓝本,用C++做一套基础的网络库,去除掉对boost库的依赖,并且用C++1y的特性简化代码,如果可以还会考虑去除对部分posix接口的依赖(至少在基础库中去除),还有使用Result<T,E>代替异常机制.这两项是后话了,得把其他坑填完才能考虑.

muduo网络库分基础/网络两部分,基础部分主要封装了日志、线程和时间,而C++11中封装了线程和时间,所以我打算先从这两处下手.本篇就先谈线程了.

使用std::atomic

muduo库基于__sync_fetch_and_add等编译器扩展的函数封装了一个AtomicIntegerT类,而C++11提供std::atomic来进行原子操作,省略了一次自己封装.

使用std::mutex

posix提供了pthread_mutex_t来实现线程互斥锁,同时还提供读写锁、自旋锁、信号量等.按照Linux多线程服务端编程一书(一下简称为muduo书)的建议,不要使用互斥锁以外的技术来实现线程同步.muduo库中也只封装了简单的互斥锁.

C++11提供了std::mutex,但是它并没有保存持有者(holder)的信息,所以仍需要对它做一层封装.

同时由于std::lock_guard的存在,完全不需要自己实现类似muduo::MutexLockGuard的守卫.

使用std::condition_variable

条件变量一般与互斥锁配合使用,posixC++11都提供了相关接口(std::condition_variable),稍稍封装一下就好.

然而这里遇到了和时间有关的函数wait_*,保守起见暂不使用std::chrono.

使用std::thread代替pthread?

目前为止一切良好运作,下一步就是用std::thread代替pthread了.

很多博客都做过std::threadpthread的对比,对于我个人来说,除了std::thread“创建即启动”以外并没有什么不爽的地方,不能cancel/kill什么的其实问题不是很大,muduo书中也提到通常正确的设计下不会使用它们;也没有优先级,这也是小事.

然而问题来了,muduo库中大量使用了__thread关键字.__thread是gcc内置的线程局部存储设施,比pthread_key_t高效,然而C++11中并没有类似的关键字,甚至连类似pthread_key_t的功能也没有.要解决这个问题应该不是很难,不过我在这里进了坑,目前还没爬出来.

muduo库使用muduo::CurrentThread封装了一部分__threadpthread_key_t,在muduo::ThreadLocalSingleton中封装了另一些.而std::this_thread除了std::thread::id以外什么都获取不到,所以我想用一个全局的std::unordered_map来代替,不过工程量有点大,而且可能带来不小的性能损失,再加上在实践途中被大量编译错误淹没不知所措,只能宣告第一次尝试失败.在完成其他部分的改造后再来操作.


本博的原创作品作品采用知识共享署名 2.5 中国大陆许可协议 进行许可,欢迎转载,但转载请注明出处,并保持转载后文章内容的完整。
本文链接:http://fallenwood.github.io/2017/01/01/cpp-11-threads-pool/