百度 Apollo 8.0 Cyber 源代码分析(二)
2024-11-24 本文已影响0人
RonZheng2010
2 cyber的基本组件
2.1 Slot、Signal与Connection
Slot和Signal实现一对多的通知。
Slot保存一个回调函数。
- 成员cb_保存这个回调函数,成员函数operator()会调用它。
Signal保存一个Slot实例的列表。
- 成员函数Connect()创建一个Slot实例,并保存到slots_中。
- 成员函数operator()遍历slots_,调用Slot实例的operator()。可以像调用函数一样调用它Signal的实例。
Connection保存Slot实例和它所属的Signal之间的关联关系。
- slot_和signal_分别是Slot实例和Signal实例。
2.2 Blocker
Blocker包括两个先进先出队列:published_msg_queue_和observed_msg_queue_。
- Publish()向published_msg_queue推入消息
- Subcribe() 指定回调函数,从published_msg_queue_订阅消息,这些回调函数保存在成员published_callback_。
- Observed()会将published_msg_queue_复制到observed_msg_queue_,这样读取时,就不需要加锁了。
2.3 CacheBuffer与ChannelBuffer
CacheBuffer是一个环形缓存,这是一个模板类,模板参数是元素类型。
- 成员buffer_是一个vector,提供缓存空间。成员capacity_是可以保存的元素数量。
- 成员函数Tail()/Head()/at()访问指定环形缓存的位置,成员函数Fetch()从指定位置取出元素。
关于ChannelBuffer,
- 成员channel_id_ 是channel id。
- 成员buffer_包括一个CacheBuffer实例。
2.4 DataNotifier / DataDispatcher / DataVisitor
DataNotifier负责消息到达的通知。
- 成员notifies_map_是一个从channel_id到vector的映射,这个vector是一组回调函数。
- 成员函数AddNotifier向指定channel的vector推入一个回调函数。
- 成员函数则调用指定channel的vector中的所有回调函数,作为消息通知。
DataDispatcher负责向一组访问者派发消息。
- 成员buffers_map_是一个从channel_id到vector的映射。这个vector是一组CacheBuffer实例,用于缓存收到的消息。
- 成员notifier_ 是DataNotifier实例,用于通知访问者消息到达。
- 成员函数AddBuffer()向成员bufers_map_中对应channel_id的vector,推送一个CacheBuffer实例。AddBuffer()的参数是一个ChannelBuffer实例,CacheBuffer实例从它获得。
- Dispatch)派发消息。
- 在对应channel_id的vector中的所有CacheBuffer实例,保存一个消息副本;
- 通过成员notifier_ 通知这个channel的所有访问者。
DataVisitor打包了对DataDispatcher和DataNotifier的调用。它派生自DataVisitorBase。
关于DataVisitorBase,
- 成员notifier_ 是一个回调函数,使用者通过成员函数RegisterNotifyCallback()设置。
- 成员data_notifier_ 是唯一的DataNotifier实例。
- 成员next_msg_index_ 是一个索引值,指向唤醒缓存CacheBuffer中的位置。
关于DataVisitor,
- 每个DataVisitor实例从DataDispatcher监听/接收一个channel的消息。每个channel可以有多个DataVisitor实例接收。
- 成员buffer_是一个ChannelBuffer实例。
- 在DataVisitor的构造函数中,
- 调用DataDispatcher::AddBuffer()加入自己的buffer_,这样当消息到达时,会在这里保存一份;
- 调用DataNotifier::AddNotifier(),加入自己的notifier,这样就能得到消息通知。得到通知时,DataVisitorBase的成员notifier_会被调用。
- 成员函数TryFetch()从next_msg_index_指定的环形缓存当前位置获取消息。
DataVisitor一般的使用流程是;
- 指定channel创建DataVisitor实例,调用RegisterNotifyCallback()设置回调函数,假设名字为notifier。
- 当这个channel有消息到达时,DataDispatcher会调用notifier。
- 这时可以调用DataVisitor::TryFetch()得到消息。
相关链接
百度 Apollo 8.0 Cyber 源代码分析(一)
百度 Apollo 8.0 Cyber 源代码分析(二)
百度 Apollo 8.0 Cyber 源代码分析(三)
百度 Apollo 8.0 Cyber 源代码分析(四)
百度 Apollo 8.0 Cyber 源代码分析(五)