57 lines
6.1 KiB
Markdown
57 lines
6.1 KiB
Markdown
# 项目细节规范
|
||
|
||
## 代码组织
|
||
|
||
* `.hpp` 只放业务契约和必要前置声明,不允许出现函数体;构造函数、薄壳函数及模板函数也只能声明。模板定义统一放对应 `.ipp`
|
||
,非模板定义放 `.cpp` 或仅供头文件实例化的 `.ipp`。
|
||
* 嵌套 `Private` 在 `.hpp` 只写 `struct Private;`,完整定义、内部字段和 CRTP 定制点放在对应 `.ipp`。
|
||
* 派生 `Private` 必须继承 `Prev_Private`。可覆盖或必需的 CRTP 能力必须在 `Private` 定义处写清用途、参数、返回值、默认行为、调用时机和编译期选择优先级。
|
||
* 状态处理、算法和内部协作都实现在 `Private`;只有外部消费者需要的业务能力才在原始类声明薄壳,并通过 `d` 调用最终
|
||
`Private`。
|
||
* 替换实现时删除旧实现,不保留重复定义、兼容别名或转发层。
|
||
|
||
## 状态与接口
|
||
|
||
* 每个状态只能有一个权威来源。双缓冲交换后的当前结构就是稳定读面,跨对象直接读取该结构;禁止为无锁访问再复制一份快照、View、镜像字段或同步缓存。
|
||
* `Prop` 保存外部可读写的业务属性,`State` 保存实现向外发布的运行结果,`Private` 保存实现细节;三者不得互相复制并手工同步。
|
||
* 每个 `Def` 定义层自动以自身类型生成 `Base_Tag`;Prop、State、Private 分别在隔离的标签空间中复用该标签,禁止再声明
|
||
`XXX_Prop_Tag`、`XXX_State_Tag` 或 `XXX_Private_Tag`。
|
||
* 依赖可以选择 Prop/State 的单字段或整个 `Base_Tag` 层;字段写入必须同时发出字段级和所属层级变更,使用方按实际重建粒度选择一种依赖。
|
||
* 整体对象依赖只表达依赖图中的拓扑顺序,不传播 dirty;准备顺序、绘图顺序等业务含义由各自 Tag 解释。具体字段依赖才用于对应
|
||
Tag 的 dirty 传播,例如绘图缓存失效。
|
||
* Kernel `Scene` 只负责 2D/3D 共有的 Prepare 数据阶段;Paint、缓存失效、像素合成和异步后端提交由对应渲染模块自己的
|
||
Scene、Tag 与 Taskflow 负责。
|
||
* `Scene::Private` 是输入事件流的唯一所有者:外部转移事件对象所有权,并发提交到 Def 注册的 MPMC
|
||
三缓冲;收集、内部渲染、外部查询分别占用一份队列,Prepare 入口只在交换锁下轮换三者并清空过期查询队列。事件不得独立触发帧。2D
|
||
按 Renderable 区域与 Paint 顺序形成接受链,区域默认整个 viewport;3D 无等待提交渲染域,满载时保留当前事件供下一次 Prepare
|
||
重试。
|
||
* 帧由 Frame_Policy 创建、持有和复用;每次 `render(frame*)` 只借用该帧并在完成回调返回同一地址。Scene、异步后端和 Web
|
||
层只向帧写入固定语义的单调时间点与原始耗时,不保存平均值、分位数或波动等衍生统计。
|
||
* Frame_Policy 借用抽象 Scene 并调用 `render(frame*)`;`fixed_rate` 只由其具体 Policy 子类持有的 Frame_Scheduler 周期时钟驱动,
|
||
完成回调不得改变 deadline。`maximum_rate` 子类只在 Scene 开放后续生产或 Policy 回收物理帧槽后异步投递下一次生产任务;
|
||
回调不得直接重入 `render()`、不得同步等待。Scene 回调发布 2D 原生 BGRA 或 3D 原生 RGBA;每个 Plot 只服从自身
|
||
Frame_Policy。Gallery 仅按 Plot 完成帧的到达顺序更新对应图集槽位,不拥有采样时钟、帧准入、合并或丢帧策略; 每次槽位更新均在唯一串行
|
||
Taskflow 媒体 DAG 中组成图集并由 FFmpeg/libx264 编码 H.264 Annex-B。Drogon WebSocket 只传输压缩 access
|
||
unit,不得用在途窗口反向跳过已通过 Plot 策略的帧;浏览器由 WebCodecs 解码后按槽位提交各 Plot Canvas。Plot 输入和控制也统一使用
|
||
Drogon WebSocket。
|
||
* 帧策略及其时钟实现统一归属 `kernel/src/kernel/Frame_Policy`。Manual、Fixed-rate 和 Maximum-rate 分别由具体 Policy 子类表达,
|
||
禁止在基类中再保存模式联合体。Policy 直接接收 Scene 回调并通过 `double_buffer/model.hpp` 发布自身 State,不建立事件流或
|
||
Taskflow consumer。模式替换必须调用旧 Policy 的异步 `stop(callback)`;停止排空全部 Scene 借用和媒体分派后,在回调中创建 新
|
||
Policy。禁止同步等待、策略状态快照、策略历史、轮询累加器或重复诊断字段。
|
||
* 相机是 3D Scene 组件,只允许定义在 `render_3D/camera`;Kernel 和 2D 不得依赖相机类型。Web 层只为已有 `Camera_3D`
|
||
增加协议描述,不复制相机配置。Gallery 服务同一时刻只允许一个页面实例持有;该页面的所有 Plot 连接共享页面令牌,其他标签页或浏览器实例必须被拒绝。
|
||
* `Time_Axis` 是时间与 tick 的唯一权威来源;使用层先推进时间轴,再把同一 tick 分发给所有相关数据图元。时间窗口从第一条数据起始终锚定最新
|
||
tick,未产生数据的槽位保持背景。
|
||
* 图表选区保存两根轴上的数据范围,绘制时才映射为像素;选区作为独立 Renderable 在使用层与图元组合,禁止在各图元内复制选区状态。
|
||
* `Root` 只保存一个最终 `Private` 指针;`Builder::build()` 校验成功后创建并挂接完整 Private,`Root` 通过公共 Private
|
||
基类的虚析构统一释放。禁止直接公开该指针。
|
||
* 能从权威结构查询或计算的数据即时获取,不保存为成员。类只保存自身职责需要且无法推导的状态,并检查每个新增成员的读写者和生命周期。
|
||
* 公共接口只表达业务语义,不暴露 `Private`、内部指针、线程状态或缓冲区角色;接口保持正交,不增加空配置、未完成接口、无消费者统计或只做转发的
|
||
getter/setter。
|
||
|
||
## 注释与修改
|
||
|
||
* 普通字段使用对齐的同行 `/* ... */` 注释,写清含义、单位、有效条件和生命周期;函数、类型及 CRTP 契约使用声明前注释。
|
||
* 审计和重命名应一次完成结构、引用、测试及文档闭环。任何 fallback 必须先写明触发条件、影响范围和验证方式,再实施。
|
||
* 修改后完整编译相关目标;需要运行程序时按 `AGENTS.md` 通过 CDB 执行。
|