为什么需要通知机制(Notify)

当订阅端游数据时可以及时被唤醒,减少CPU资源占用

涉及技术

1. 观察者模式

单个Publisher , 多个Subscriber都能被通知到

2. 信号量

底层依赖信号量实现夸进程通知

操作系统提供的原语:

  • sem_wait() — 没有信号 → 线程从 CPU 调度队列移除,零 CPU 占用
  • sem_post() — 发信号 → 把等待的线程放回调度队列,微秒级唤醒

Iceoryx(冰羚)实现方式

1. 信号量 需要跨进程使用,所以创建后需要被放在共享内存中

ConditionVariableData(信号量对象)

  • 在创建 WaitSet / Listener 对象时 由Roudi创建,具体接口:runtime::PoshRuntime::getInstance().getMiddlewareConditionVariable() 分配
  • 当用户调用Listener的attachEvent时会被放到 ChunkQueueData 对象中

补充:WaitSet / Listener中有除了信号量,还有通知槽,允许多个Subscriber对象进行订阅

ChunkQueueData

  • 说明:Subscriber侧的共享内存队列订阅成功后队列地址可被Publisher拿到
  • 位置: 管理段共享内存(Subscriber 的数据队列)
  • 作用: Subscriber 端的消息队列 + 通知绑定信息

    内部变量:

  • RelativePointer<ConditionVariableData> m_conditionVariableDataPtr (信号量

  • m_conditionVariableNotificationIndex (信号槽位置

2. 通知

在Publisher端,调用流程:

publish()>>>

ChunkDistributor::deliverToAllStoredQueues >>>

ChunkQueuePusher::push >>>

ConditionNotifier(*getMembers()->m_conditionVariableDataPtr.get(),

*getMembers()->m_conditionVariableNotificationIndex)

.notify();

说明:m_conditionVariableDataPtr / m_conditionVariableNotificationIndex 在 Publisher端被拿到,直接使用m_conditionVariableDataPtr sem_post(),m_conditionVariableNotificationIndex告诉对端,是哪个Subscriber

3. 接收

Listener和WaitSet调用 wait(), 就会一直阻塞线程,直到监听的其中一个Subscriber的信号量被触发

4. Listener和WaitSet的区别

Listener内部有thread,执行了wait,同时客户注册了回调被存储在Event中,轮训通知槽掉用对用的回调对象;

listener.attachEvent(subscriber, SubscriberEvent::DATA_RECEIVED, callback);
    // → m_conditionVariableDataPtr 也被设置了

WaitSet需要用户自动执行wait,并自己轮训判断拿到wait接口返回的不同的subscriber,执行不同的操作

waitSet.attachState(subscriber, HAS_DATA);
   while (true) {
        auto notifications = waitSet.wait();
        // ...
    }
    // → m_conditionVariableDataPtr 被设置了

总结

冰羚融合了信号量和观察者模式,在共享内存上实现了跨进程的Publisher和Susbcriber之间的信号通知功能,非常值得学习!!~

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐