//线程池二
//抽取队列代码
#指示 一次

#包含<条件变量>
#包含<互斥锁>
#包含<队列>
//其他线程池可复用它
元<型名 T>类 队列{//可压任意T类型
公:
空 压(常 T&项){
{
域锁 锁(互斥锁);
队列.压(项);
}
条件.通知一个();
}//要提供左值版`压`.
//注意:不能用`完美转发`来统一`左值和右值引用`

空 压(T&&项){//队列是模板,构造时,已推导了T的类型,因而T&&是右值引用,而非`通用引用`.
{
域锁 锁(互斥锁);
队列.压(移动(项));
}
条件.通知一个();
}

极 弹(T&项){
独锁 锁(互斥锁);
条件.等待(锁,[&](){中!队列.空的()||停止;});
如(队列.空的())
中 假;
项=移动(队列.前());
队列.弹();
中 真;
}

大小型 大小()常{
域锁 锁(互斥锁);
中 队列.大小();
}

极 空的()常{
域锁 锁(互斥锁);
中 队列.空的();
}

空 停止(){
{
域锁 锁(互斥锁);
停止=真;
}
条件.通知所有();
}

私:
条件变量 条件;
可变 互斥锁 互斥锁;
队列<T>队列;
极 停止=假;
};
-------------
//简单线程池
#包含"安全队列.h"
#包含<函数>
#包含<线程>
#包含<向量>

用 工作项=函数<空()>;
类 简单池{
公:
显 简单池(大小型 线程=线程::硬件并行()){
对(大小型 i=0;i<线程;++i)
工作者.原后([本]{
对(;;){
函数<空()>任务;
如(!队列.弹(任务)){中;}
如(任务){任务();}
}
});
}

空 入列(工作项 项){队列.压(移动(项));}
//1行入列代码了.
~简单池(){
队列.停止();
对(动&t:工作者){t.合并();}
}

私:
队列<工作项>队列;
向量<线程>工作者;
};
-------------
//多线程多队列的线程池
#指示 一次
#包含"安全队列.h"
#包含<c断定>
#包含<函数>
#包含<线程>
#包含<向量>

类 多池{
公:
显 多池(
大小型 线程号=线程::硬件并行())
:队列(线程号),线程号(线程号){
动 工作者=[本](大小型 标识){
当(真){
函数<空()>任务{};
如(!队列[标识].弹(任务))断;
如(任务){任务();}
}
};

工作者.保留(线程号);
对(大小型 i=0;i<线程号;i++){
工作者.原后(工作者,i);
}
}

整 按标识调度(函数<空()>函数,大小型 标识=-1){//提供添加任务的接口.不加`入列`接口,是因为,任务可放入任意线程队列,也可放入指定的线程中.
如(函数==空针){中-1;}
如(标识==-1){
标识=随机()%线程号;
队列[标识].压(移动(函数));
}异{
断定(标识<线程号);
队列[标识].压(移动(函数));
}

中 0;
}

~多池(){
对(动&队列:队列){队列.停止();}
对(动&工作者:工作者){工作者.合并();}
//停止队列,退出线程.
}

私:
向量<队列<函数<空()>>>队列;
大小型 线程号;
向量<线程>工作者;
//线程与队列一一对应,用标识关联,线程只需要从对应队列中`取出任务`执行即可
};
---------
空 测试简单池1(){
简单池 池;
池.入列([]{输出<<"你好\n";});
串 串="世界";
池.入列([串=移动(串)]{输出<<"你好"+串<<'\n';});
}

空 测试多池1(){
多池 池;
池.按标识调度([]{输出<<"你好\n";});
串 串="世界";
池.按标识调度([串=移动(串)]{输出<<"你好"+串<<'\n';});
}
----
#包含<io流>
#包含<时间>
#包含<原子>
#包含"简单池.h"
#包含"多池.h"

类 域计时器{
公:
域计时器(常 符*名)
:m名(名),m头(时间::高精钟::现在()){}
~域计时器(){
动 尾=时间::高精钟::现在();
动 时长=时间::时转<时间::纳秒>(尾-m头);
输出<<m名<<":"<<时长.数()<<"ns\n";
}

私:
常 符*m名;
时间::时间点<时间::高精钟>m头;
};

常 大小型 计数=1'000'000;
常 大小型 重复=10;

空 基准(){
原子<整>数=0;
域计时器 计时器("简单池");
{
简单池 池;
对(大小型 i=0;i<计数;i++){
池.入列([i,&数]{
数++;整 x=0;
动 重复=重复+(重复+(随机()%5));
对(大小型 j=0;j<重复;j++){
x=i+随机();
}
});
}
}
断定(数==计数);
}

空 基准1(){
原子<整>数=0;
域计时器 计时器("多池");
{
多池 池;
对(大小型 i=0;i<计数;i++){
池.按标识调度([i,&数]{
数++;整 x=0;
动 重复=重复+(重复+(随机()%5));
对(大小型 j=0;j<重复;j++){
x=i+随机();
}
});
}
}
断定(数==计数);
}

整 主(){
对(大小型 i=0;i<6;i++){
基准();基准1();
}//多池为简单池的2倍.
输出<<"你好,世界!"<<行尾;
中 0;
}