同步客户机
头文件:<dlt698/service/sync.hpp>,命名空间 dlt698::service。
基本用法
同步适配在统一的异步核心上等待,不创建线程。
两种驱动方式
Drive 是 std::function<void(std::chrono::milliseconds)>,两种模式二选一。
显式驱动
传入 drive 回调,调用线程反复执行它来推进事件循环:
或者在测试里用虚拟时钟:
drive 回调会被反复调用。如果它自己长时间阻塞,事务超时就不会触发,请求会一直等下去。run_for / advance 传一个有限时长是正确的做法。
显式驱动的优势是虚拟时钟也能产生超时——ManualExecutor::advance 推进虚拟时间,Session 的 request_timeout 照样生效。
外部线程驱动
不传 drive,此时必须由其他线程持续驱动 IoRuntime::run():
这是命令行长驻进程的典型模式。线程结束时机见TCP 通道的退出顺序说明。
死锁防护
同步等待最危险的错误是在事件循环回调里再同步等待——那会让执行器永远等不到自己的响应。
库对此有两道防护:
Session::in_executor_thread() 可以让你自己提前判断:
错误归属
- 超时由
Session管理,不是同步适配器。适配器只是等待Session的回调。 - 应用必须保持运行时进展。不传 drive 且没有外部线程时,同步调用会一直等下去。
- 销毁适配器前先结束所有同步调用。
~SyncClientService释放等待状态,仍在进行的调用会拿到不确定的结果。
drive 抛异常
drive 抛异常时返回 io_error 并投递取消。后续的完成状态由共享对象持有,不会引用已经返回的栈帧。
不重试
set、action 及其列表版本不自动重试。超时不能证明远端未执行,重复调用有副作用。需要幂等保证请自己在应用层处理。
完整示例
cpp/examples/memory_mutation.cpp 演示了完整的同步读写/方法与串行链路适配:内存通道两端都经过 FE 和 33 位间隔处理,完成同步 CONNECT → SET → ACTION → GET → RELEASE,输出 SET DAR=0 ACTION DAR=0 GET UInt16=42。代码见第一个程序。