C++线程池二

//原文:http://purecpp.org/detail?id=2261,
//线程池二
//抽取队列代码
#指示 一次

#包含<条件变量>
#包含<互斥锁>
#包含<队列>
//其他线程池可复用它
<型名 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;
}
posted @   zjh6  阅读(11)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示