菜鸟笔记
提升您的技术认知

brpc 笔记

bthread(一) 前言bthread(二) 线程模型及bthreadbthread(三) bthread数据结构bthread(四) bthread用户接口和代码执行路径bthread(五) 无锁队列rq的代码实现bthread(六) 小结brpc的精华bthread源码剖析brpc介绍、编译与使用brpc源码解析(一)—— rpc服务添加以及服务器启动主要过程brpc源码解析(二)—— brpc收到请求的处理过程brpc源码解析(三)—— 请求其他服务器以及往socket写数据的机制brpc源码解析(四)—— bthread机制brpc源码解析(五)—— 基础类resource pool详解brpc源码解析(六)—— 基础类socket详解brpc源码解析(七)—— worker基于parkinglot的bthread调度brpc源码解析(八)—— 基础类eventdispatcher详解brpc源码解析(九)—— 基础类workstealingqueue详解brpc源码解析(十)—— 核心组件bvar详解(1)简介和整体架构brpc源码解析(十一)—— reducer类和adder类解析brpc源码解析(十二)—— 核心组件bvar详解 agentgroup类详解brpc源码解析(十三)—— 核心组件bvar详解(4)combiner详解brpc源码解析(十四)—— 核心组件bvar详解 sampler详解brpc源码解析(十五)—— bthread栈创建和切换详解brpc源码解析(十六)—— 作为client的连接建立和处理详解brpc源码解析(十七)—— bthread上的类futex同步组件butex详解brpc源码解析(十八)—— mpsc队列executionqueue详解brpc源码解析(十九)—— 双buffer数据结构doublybuffereddata详解brpc源码解析(二十)—— 用于访问下游的channel类详解

bthread(三) bthread数据结构-ag真人游戏

阅读 : 346

taskcontrol

base::atomic _ngroup;
taskgroup** _groups;                // taskgroup对象指针的数组
base::atomic _concurrency;     // tc启动时的默认起的pthread数量,可以理解为bthread并发度数量,静态开关配置为9
std::vector _workers;    // pthread线程标识符的数组,表示创建了多少个pthread worker线程,每个pthread worker线程应拥有一个线程私有的taskgroup对象。
parkinglot _pl[parking_lot_num];    // parkinglot类型的数组。parkinglot对象用于bthread任务的等待-通知
siganl_task():通知一部分parkinglot里的worker说有新bthread被创建出来啦,提醒worker去偷
steal_task():遍历所有worker去偷,防止某一个thread在某一个taskgroup一直得不到run被饿死的情况

创建bthread只有两种情况(鸡生蛋蛋生鸡)

1、本身在bthread内创建bthread:因为当前bthread肯定跑在某个worker里,那就把新创建的bthread加到该worker的_rq里,这样locality貌似好一些

2、在pthread里创建bthread:taskcontrol随机挑个worker(也就是taskgroup),放到该worker的_remote_rq里(存放所有非worker创建的bthread),这个队列是个一读者多写者的队列,难做wait-free,用mutex保护

【调度优先级】

  1. 基本调度:bth在每个先进先出的rq队列中逐个执行
  2. 若本地(本worker)rq没有了则去本地_remote_rq里pop一个放到runq里运行
  3. 去其他worker的_rq里偷
  4. 去其他worker的_remote_rq里偷

【tips】worker拿到tid如果无阻塞就一定会执行完,有阻塞就从rq先拿掉放到队尾,再运行下个bthread,唤醒有别的机制。

【tips】如果一个worker内有一些pthread级别的阻塞,相当于这个worker就被阻塞了,那么其他worker会偷走该worker内被阻塞的bthread,保证整个系统可以顺利地跑在多核上。

taskgroup

contextualstack* _main_stack;       // tg单独持有的栈
bthread_t _main_tid;                // tg“调度线程”
workstealingqueue _rq;   // 按序执行的bthread队列
remotetaskqueue _remote_rq;         // pthread下创建bthread会放入的队列
taskmeta* _cur_meta;                // 当前正在执行的bthread的taskmeta对象的地址

taskgroup interface(基本函数,用户不可见)

切线程相关

  • sched:封装sched_to,根据调度策略运行下一个要运行的bthread
  • sched_to(bth):切换到目标bth运行(底层用汇编实现,较为复杂的栈跳转逻辑,非常核心但并不是核心创新)

放队列相关

  • ready_to_run(bth):第1个动作把bth放到_rq,第2个动作调signal_task去唤醒一个任务去执行该bth
  • ready_to_run_remote:第1个动作加锁,第2个动作把bth放到_remote_rq,第3个动作调signal_task去唤醒一个任务去执行该bth
  • 补充:上述两个函数都有个参数signal,当新push一个bth时,会判断是否需要signal去提醒其他worker去偷,比如当前_rq很忙,我就希望别的赶紧来偷

【盗图】

网站地图