├── Cpp11ThreadPool ├── Main.cpp ├── threadpool.h ├── Cpp11ThreadPool.vcxproj.filters └── Cpp11ThreadPool.vcxproj ├── Cpp11ThreadPool.sln └── README.md /Cpp11ThreadPool/Main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanttobeno/Cpp11ThreadPool/HEAD/Cpp11ThreadPool/Main.cpp -------------------------------------------------------------------------------- /Cpp11ThreadPool/threadpool.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanttobeno/Cpp11ThreadPool/HEAD/Cpp11ThreadPool/threadpool.h -------------------------------------------------------------------------------- /Cpp11ThreadPool.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cpp11ThreadPool", "Cpp11ThreadPool\Cpp11ThreadPool.vcxproj", "{B91CA619-DF0D-4FBE-8410-039D336771BD}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {B91CA619-DF0D-4FBE-8410-039D336771BD}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {B91CA619-DF0D-4FBE-8410-039D336771BD}.Debug|Win32.Build.0 = Debug|Win32 16 | {B91CA619-DF0D-4FBE-8410-039D336771BD}.Release|Win32.ActiveCfg = Release|Win32 17 | {B91CA619-DF0D-4FBE-8410-039D336771BD}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /Cpp11ThreadPool/Cpp11ThreadPool.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C++ 11 Threadpool 2 | 3 | 学习C++ 11时遇到的一个线程池,使用了很多C++ 11的新特性, 4 | 流程和传统的差不多,但是代码简洁了很多。 5 | 6 | 7 | [From lzpong github](https://github.com/lzpong/threadpool) 8 | 9 | --- 10 | based on C++11 , a mini `threadpool` , accept variable number of parameters. 11 | 基于C++11的线程池,简洁且可以带任意多的参数 12 | 13 | 管理一个任务队列,一个线程队列,然后每次取一个任务分配给一个线程去做,循环往复。 14 | 有意思的是,限制只创建一个线程,这样就是一个完全的任务队列了。 15 | 16 | 线程池,可以提交变参函数或拉姆达表达式的匿名函数执行,可以获取执行返回值 17 | 18 | 代码不多,**上百行代码就完成了 线程池**, 并且, 看看 `commit`, 哈, 不是固定参数的, 无参数数量限制! 这得益于可变参数模板. 19 | 20 | 21 | 22 | *为了避嫌,先进行一下版权说明:代码是 me “写”的,但是思路来自 Internet, 特别是[这个线程池实现](https://github.com/progschj/ThreadPool)(基本 copy 了这个实现,加上[这位同学的实现](http://blog.csdn.net/zdarks/article/details/46994607)和解释,好东西值得 copy ! * 23 | **然后综合更改了下,更加简洁** 24 | *)。* 25 | 26 | ##C++11语言细节 27 | 即使懂原理也不代表能写出程序,上面用了众多c++11的“奇技淫巧”,下面简单描述之。 28 | 29 | 1. using Task = function 是类型别名,简化了 typedef 的用法。function 可以认为是一个函数类型,接受任意原型是 void() 的函数,或是函数对象,或是匿名函数。void() 意思是不带参数,没有返回值。 30 | 2. pool.emplace_back([this]{...}) 和 pool.push_back([this]{...}) 功能一样,只不过前者性能会更好; 31 | 3. pool.emplace_back([this]{...}) 是构造了一个线程对象,执行函数是拉姆达匿名函数 ; 32 | 4. 所有对象的初始化方式均采用了 {},而不再使用 () 方式,因为风格不够一致且容易出错; 33 | 5. 匿名函数: [this]{...} 不多说。[] 是捕捉器,this 是引用域外的变量 this指针, 内部使用死循环, 由cv_task.wait(lock,[this]{...}) 来阻塞线程; 34 | 6. delctype(expr) 用来推断 expr 的类型,和 auto 是类似的,相当于类型占位符,占据一个类型的位置;auto f(A a, B b) -> decltype(a+b) 是一种用法,不能写作 decltype(a+b) f(A a, B b),为啥?! c++ 就是这么规定的! 35 | 7. commit 方法是不是略奇葩!可以带任意多的参数,第一个参数是 f,后面依次是函数 f 的参数(*注意:参数要传struct/class的话,建议用pointer,小心变量的作用域*)! 可变参数模板是 c++11 的一大亮点,够亮!至于为什么是 Arg... 和 arg... ,因为规定就是这么用的! 36 | 8. commit 直接使用智能调用stdcall函数,但有两种方法可以实现调用类成员,一种是使用 bind: .commit(std::bind(&Dog::sayHello, &dog)); 一种是用 mem_fn: .commit(std::mem_fn(&Dog::sayHello), &dog); 37 | 9. make_shared 用来构造 shared_ptr 智能指针。用法大体是 shared_ptr p = make_shared(4) 然后 *p == 4 。智能指针的好处就是, 自动 delete ! 38 | 10. bind 函数,接受函数 f 和部分参数,返回currying后的匿名函数,譬如 bind(add, 4) 可以实现类似 add4 的函数! 39 | 11. forward() 函数,类似于 move() 函数,后者是将参数右值化,前者是... 肿么说呢?大概意思就是:不改变最初传入的类型的引用类型(左值还是左值,右值还是右值); 40 | 12. packaged_task 就是任务函数的封装类,通过 get_future 获取 future , 然后通过 future 可以获取函数的返回值(future.get());packaged_task 本身可以像函数一样调用 () ; 41 | 13. queue 是队列类, front() 获取头部元素, pop() 移除头部元素;back() 获取尾部元素,push() 尾部添加元素; 42 | 14. lock_guard 是 mutex 的 stack 封装类,构造的时候 lock(),析构的时候 unlock(),是 c++ RAII 的 idea; 43 | 15. condition_variable cv; 条件变量, 需要配合 unique_lock 使用;unique_lock 相比 lock_guard 的好处是:可以随时 unlock() 和 lock()。 cv.wait() 之前需要持有 mutex,wait 本身会 unlock() mutex,如果条件满足则会重新持有 mutex。 44 | 16. 最后线程池析构的时候,join() 可以等待任务都执行完在结束,很安全! 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Cpp11ThreadPool/Cpp11ThreadPool.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {B91CA619-DF0D-4FBE-8410-039D336771BD} 15 | Win32Proj 16 | Cpp11ThreadPool 17 | 10.0.16299.0 18 | 19 | 20 | 21 | Application 22 | true 23 | v120_xp 24 | Unicode 25 | 26 | 27 | Application 28 | false 29 | v120_xp 30 | true 31 | Unicode 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | true 45 | 46 | 47 | false 48 | 49 | 50 | 51 | 52 | 53 | Level3 54 | Disabled 55 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 56 | 57 | 58 | Console 59 | true 60 | 61 | 62 | 63 | 64 | Level3 65 | 66 | 67 | MaxSpeed 68 | true 69 | true 70 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 71 | 72 | 73 | Console 74 | true 75 | true 76 | true 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | --------------------------------------------------------------------------------