架构(v2)
Dart / Flutter 应用 └─ Dart 包(DartCppBridge、codec、FFI bindings) └─ FFI 二进制帧原生库 ├─ Runtime(Asio io_context + IoContextScheduler + blocking pool) ├─ Session registry(每个 Dart isolate 一个 session) ├─ Wire dispatch(帧路由和 method_id) ├─ Codec(ByteReader / ByteWriter) ├─ Channel 与 stdexec scheduler 适配器 └─ 业务代码(BRIDGE_SYNC / BRIDGE_ASYNC / BRIDGE_NORMAL)生成器扫描 BRIDGE_* 标记,并生成 wire dispatch、Dart FFI bindings 和
Dart API。v2 的异步 C++ 声明使用 stdexec::task<T> 或其他受支持的 sender。
Runtime
Section titled “Runtime”进程级 dcb::Runtime 负责:
- 一个通过
IoContextScheduler暴露的 Asio io scheduler(默认一个 runner, 可在启动前配置); - blocking Asio thread pool;
- 支持 scheduler 的通道和 timer;
- Dart post callback 与 session 生命周期。
生成的 task 具有 scheduler affinity。v2 不再把外部 loop 封装成 async-simple executor;外部 loop 提供可以组合 sender 的普通 stdexec scheduler。
Dart → dcb_invokeSyncMethod → io 线程解码请求 → 调用 BRIDGE_SYNC 函数 → 编码 responseOk / responseErr → 返回 Dart函数必须短小且完全不阻塞。
Dart → dcb_invokeAsyncMethod → 解码请求 → 创建 stdexec::task<T> → starts_on(io_scheduler, task) → co_await sender / channel / timer / DartFn → 向 Dart session 发送 responseOk / responseErr生成的协程 dispatch 使用零捕获 IIFE。参数进入协程帧,使 dispatch 函数返回 后状态仍然有效。
Normal
Section titled “Normal”Dart → dcb_invokeNormalMethod → 普通 C++ 函数投递到 blocking pool → 编码结果或异常 → 向 Dart 发送 responseStream 与 DartFn
Section titled “Stream 与 DartFn”Stream 使用 StreamSink<T> 发送 streamData、streamEnd、
streamErr 帧。Dart 取消订阅只停止接收,原生操作可能继续运行,
之后的 sink 调用会被丢弃。
DartFn 调用发送 dartFnCall 帧并等待 oneshot sender。Dart 执行闭包
期间 io 线程挂起,收到 reply 后再恢复。
- io 线程:帧 dispatch、scheduler 工作、非阻塞 timer 和发起 DartFn;
- blocking pool:
BRIDGE_NORMAL和spawn_blocking工作; - 外部 loop 线程:用户提供的 stdexec scheduler;
- Dart isolate:Dart 代码和闭包执行。
不要阻塞 io scheduler runner。只在 worker 或外部线程使用
dcb::sync_wait,取消使用 stop token 做协作式传播。多个 io runner 也不会
取消这条规则:原始 stdexec::sync_wait 会一直占用调用它的 runner,所有
runner 都等待该 scheduler 上的任务时仍会让 scheduler 死锁。