正确做法是每个主题维护独立线程安全优先队列,分发逻辑与订阅者模型解耦,策略通过函数对象注入,避免全局单队列阻塞及broadcastsystemmessage误用,并需防范饥饿与重复消费。

用 std::priority_queue 管理消息顺序,但别直接广播给所有人
优先级广播不是“把高优消息发得更快”,而是让每个订阅者按自己订阅的主题 + 优先级规则,独立拿到该收的消息。直接把 std::priority_queue 做成全局单队列再遍历所有订阅者广播,会破坏并发吞吐——一个慢订阅者卡住,全队列阻塞。
- 正确做法是:每个主题维护自己的线程安全优先队列(
std::priority_queue+std::mutex+std::condition_variable),生产者按主题入队,消费者线程池按需拉取 - 广播逻辑不发生在队列层,而是在分发层:当某主题有新消息,遍历该主题所有活跃订阅者,逐个投递(可异步、可带重试)
- 别用
std::greater<message></message>作为比较器后忘记重载operator>—— 编译报错invalid operands to binary expression是高频坑
广播策略必须和订阅者模型解耦,否则扩展性归零
你不能假设所有订阅者都接受“轮询”或“随机”分发;有的要广播(比如通知类),有的要竞争消费(比如任务类)。硬编码策略会让后续加新业务时反复改核心队列逻辑。
- 把分发策略抽成函数对象:比如
std::function<:vector>(const Message&, const std::vector<subscriber>&)></subscriber></:vector> - 订阅者注册时指定策略:调用
subscribe("alarm", subscriber, BroadcastStrategy),而不是在队列里写死for (auto& s : subscribers) - 注意策略执行时机:若在锁内调用策略函数,且策略里做耗时操作(如网络调用),会拖慢整个队列;应只在锁内获取目标订阅者列表,解锁后再分发
BroadcastSystemMessage 是 Windows GUI 消息机制,和你的服务端消息队列无关
搜到这个 API 就停手——它只用于向本机窗口过程广播系统级消息(如 WM_SETTINGCHANGE),不能跨进程、不支持优先级、无法自定义序列化,更不适用于多线程服务端场景。
- 误用后果:编译能过,但运行时只影响当前桌面会话的 GUI 程序,你的后台工作线程根本收不到
- 替代方案:自己实现广播分发循环,或用成熟库如
websocketpp的s.send()遍历连接,或基于epoll+ UDP 主题路由(见 Linux 广播服务实践) - 如果真要在 Windows 服务中做进程间广播,用命名管道或共享内存 + 事件通知,别碰
BroadcastSystemMessage
优先级 + 广播组合下,最容易被忽略的是“重复消费”和“饥饿问题”
高优先级消息连续到达时,低优先级消息可能永远等不到调度;多个订阅者同时处理同一消息,若没幂等设计,业务状态就乱了。
立即学习“C++免费学习笔记(深入)”;
- 防饥饿:给低优消息设“老化权重”,例如每等待 100ms,优先级值自动 +1,避免长期积压
- 防重复:广播前生成唯一
message_id,订阅者本地缓存最近 N 条 ID,收到重复则丢弃(不是靠网络层保证,而是业务层兜底) - 别依赖“广播即成功”:UDP 广播不保证送达,TCP 广播需检查
send()返回值;建议加简易 ACK 机制或至少记录发送失败日志
优先级和广播叠加后,状态分支变多,调试时别只盯队列是否空,重点看每个订阅者的接收队列深度、ACK 延迟、以及老化计数器是否生效。










