# event_comps **Repository Path**: hankhzx/event_comps ## Basic Information - **Project Name**: event_comps - **Description**: 事件订阅 分发 线程同步 状态回收 - **Primary Language**: Unknown - **License**: BSD-3-Clause - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-06-06 - **Last Updated**: 2025-06-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 这是一个事件驱动框架。 支持简单数据事件和 线程间同步事件 简单事件子类化base_event 用于不关心线程同步的抛送数据,比如串口读到数据 ,写串口数据等 线程同步事件子类化sync_event 用于线程同步的抛送数据 ,可等待另一个线程完成某某任务之后 做某某事 相较于Qt 的信号槽有如下优点 Qt event 传输性能 × | √ 性能更强 笔记本测试 单独异步ping-pong测600万/s 单独同步ping-pong测60万/s 混合测试100万/S 更友好的异步支持 × | √ 多线程 wait done 借鉴(抄袭)了go的WaitGroup。语义更加清晰 node 节点非侵入 × | √ 只需要组合使用而不是继承 注册订阅方式简单 × | √ 相较于connect ADD_LISTEN 更简短 结构符合设计原则 × | √ 信号is bad event更符合面向对象程序设计的基本原则 解决的痛点 1 Qt 信号槽无法携带结果 到前台 这他妈是个单向列车。 2 Qt 信号槽低版本(4.8)信号槽无类型检测,connect函数无法捕捉匿名函数。 3 我们写业务的时候经常没办法将一些逻辑闭环。 4 sender的矛盾,在程序框架设计的初期,我们只知道哦,这里我要输入 输出什么数据,至于数据的冲哪里了的 程序框架还没定义好我怎么知道sender是谁?这就落入了先有鸡还是先有蛋的怪圈。然后这还没处理完, 就再去构想sender怎样怎样。虽然极端了 但是大概是这样的样子。 而且有些时候我们是真的不关系sender到底是谁,我只知道我在这里要这样设计。!!! 比如状态改变有可能很多部件的逻辑都有影响状态改变的地方。 所以你是否也感觉 connect函数约束了源头和目的地 过于死板。 5 事件与节点可以组成环,依赖这一特性你能用节点和事件组合成前馈模型。 (节点就是程序中的对象 事件就是节点间的有向线段)可以组成图。 ---------------------------------------------------------------------- 关于无法闭环的梳理 ---------------------------------------------------------------------- +--------+ | button |----->--->--- 发送信号 +--------+ +--------+ | button |----->--->--- 发送信号 +--------+ +--------+ | button |----->--->--- 发送信号 +--------+ 触发以后可能是发送一个信号槽执行后面的操作逻辑 但是这些逻辑是断开的 对于后续的操作结果我们难以追踪 ---------------------------------------------------------------------- 现在这样做 ---------------------------------------------------------------------- 当前类的子线程检测 main_widget_events wait的情况 +--------+ | button |-->--+---->------->-------+------main_widget_events--->-+----->--[发送信号给UI处理成功失败] +--------+ | | | | +---------<----+ | + -<---------<--+ | ^ +---->> app_send_event(e_) ; | | +--------+ ^ | button |-->--+----->--->-->>------+ +--------+ | | +-----------<--+ ^ | | +---->> app_send_event(e_) ; ^ | +--------+ | | button |--->-+---->------->-------+ +--------+ | +----------<----+ | +---->>app_send_event(e_) ; auto e_ = std::make_shard(); app_send_event(e_) ; main_widget_events.append(e_); 在当前UI类中开启子线程处理main_widget_events中的wait 在子线程中闭环逻辑的下半部 ---------------------------------------------------------------------- 现在我们可以这样 ,构造一个事件抛送出去 并将这个事件再自己的子线程维护起来 然后,再子线程中wait/或者wait_for 子类中写出整个失败的处理方式,(比如更新状态栏/弹窗) 成功/或者失败的后续操作,就靠m_stat进行收集,具体怎木操作UI 就定义信号槽(操作UI必须用信号槽) 这样就闭环了。 ---------------------------------------------------------------------- 而且我感觉造成程序混乱的现象多半是信号槽乱用导致的。 原因有4: 1 因为信号的定义过于随意, 多半是程序的业务还没想好就先贴个信号在那。 然后由于业务的变迁,信号的语义已经不是当初的意思了。 2 造成无法回收结果,除非在定义另一半信号,但是这样不麻烦吗(不应该每一次操作就是一个对象吗?)。 3 信号是非无法结构化的,想象一个信号对象,你会一头问号???。 4 如此一来导致程序程序设计,不符合面向对象设计的基本原则。