gRPC C++源码剖析(二) ---------数据结构篇之闭包调度器

grpc_closure_scheduler

顾名思义,闭包调度器的作用就是对闭包进行调度。

下面是它的定义:

struct grpc_closure_scheduler {
  const grpc_closure_scheduler_vtable* vtable;
};

typedef struct grpc_closure_scheduler_vtable {
  void (*run)(grpc_closure* closure, grpc_error* error);
  void (*sched)(grpc_closure* closure, grpc_error* error);
  const char* name;
} grpc_closure_scheduler_vtable;

 

通过上一节的介绍,我们知道在创建闭包是会为其指定调度器,然后可以调用GRPC_CLOSURE_RUN(closure, error)在调度器上运行闭包或者调用GRPC_CLOSURE_SCHED(closure, error)在调度器上调度闭包。

其实这2个方法就是对调度器run和sched方法的调用。

调度的作用就是为闭包提供运行环境,那么gRPC提供了哪些调度器,这些调度器的作用和应用场景有是哪些呢?

 

  1. grpc_schedule_on_exec_ctx

这个调度器可能是用的最多的了,它的作用是在当前线程的ExecCtx上运行闭包。

有必要先了解一下ExecCtx。代码中对这个结构的作用说明是在调用栈上收集数据信息,是不是太抽象了。

考虑下面的场景:

A,B,C,D为4个依次调用的函数,B执行过程中调度了一个闭包1,并希望其在返回到A时执行。D同样调度了闭包2,也希望返回到A时再执行。这个时候就要使用这个调度器了grpc_schedule_on_exec_ctx.

要达到这种目的,我们要做的就是在A中声明ExecCtx,然后在B,D中调度绑定给grpc_schedule_on_exec_ctx调度器的闭包,然后在返回A时调用ExecCtx的Flush方法,这样就能达到目的了.ExecCtx内部维护了一个队列,用于存放调度给它的闭包。调用Flush方法时再依次从队列中取出闭包并运行。

在最新的gRPC版本中,简化了这种调度器的使用方法。gRPC框架为每个线程创建了这个ExecCtx,并存放在线程私有变量中,当需要时,只需要调用grpc_core::ExecCtx::Get()即可获取并使用。

可能你会问,搞这么复杂有什么意义呢?

我认为可能有以下2个好处:

1.可以使代码更加清晰

2.可以避免和缓解调用栈层次过深

你还有什么见解,欢迎来交流。

 

  1. global_executor

全局调度器,这个调度器是在gRPC启动时创建的。它内部使用一个线程池,最多会创建CPU核心数相同的线程。

在这个调度器上调度的闭包会在这些全局线程中运行。

gRPC主要使用它来运行一些阻塞的任务,如dns解析。

要使用这个调度器,使用grpc_executor_scheduler这个接口

 

好了调度器的相关知识就介绍完了,理解调度器对我们理解gRPC的代码执行流有很大的帮助。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

self-motivation

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值