接收消息
class Transport
template <typename M>
auto Transport::CreateReceiver(
const RoleAttributes& attr,
const typename Receiver<M>::MessageListener& msg_listener,
const OptionalMode& mode) -> typename std::shared_ptr<Receiver<M>> {
````略
RETURN_VAL_IF_NULL(receiver, nullptr);
if (mode != OptionalMode::HYBRID) {
receiver->Enable();
//AddSegment,AddListener
}
return receiver;
}
if (mode != OptionalMode::HYBRID) {
receiver->Enable();
//AddSegment,AddListener
}
class ShmReceiver
template <typename M>
void ShmReceiver<M>::Enable() {
if (this->enabled_) {
return;
}
dispatcher_->AddListener<M>(
this->attr_, std::bind(&ShmReceiver<M>::OnNewMessage, this,
std::placeholders::_1, std::placeholders::_2));
this->enabled_ = true;
}
dispatcher_->AddListener(
this->attr_, std::bind(&ShmReceiver::OnNewMessage, this,
std::placeholders::_1, std::placeholders::_2));
class ShmDispatcher
template <typename MessageT>
void ShmDispatcher::AddListener(const RoleAttributes& self_attr,
const MessageListener<MessageT>& listener) {
// FIXME: make it more clean
auto listener_adapter = [listener](const std::shared_ptr<ReadableBlock>& rb,
const MessageInfo& msg_info) {
auto msg = std::make_shared<MessageT>();
RETURN_IF(!message::ParseFromArray(
rb->buf, static_cast<int>(rb->block->msg_size()), msg.get()));
listener(msg, msg_info);
};
Dispatcher::AddListener<ReadableBlock>(self_attr, listener_adapter);
AddSegment(self_attr);
}
Dispatcher::AddListener(self_attr, listener_adapter);
class Dispatcher
template <typename MessageT>
void Dispatcher::AddListener(const RoleAttributes& self_attr,
const MessageListener<MessageT>& listener) {
if (is_shutdown_.load()) {
return;
}
uint64_t channel_id = self_attr.channel_id();
std::shared_ptr<ListenerHandler<MessageT>> handler;
ListenerHandlerBasePtr* handler_base = nullptr;
if (msg_listeners_.Get(channel_id, &handler_base)) {
handler =
std::dynamic_pointer_cast<ListenerHandler<MessageT>>(*handler_base);
if (handler == nullptr) {
AERROR << "please ensure that readers with the same channel["
<< self_attr.channel_name()
<< "] in the same process have the same message type";
return;
}
} else {
ADEBUG << "new reader for channel:"
<< GlobalData::GetChannelById(channel_id);
handler.reset(new ListenerHandler<MessageT>());
msg_listeners_.Set(channel_id, handler);
}
handler->Connect(self_attr.id(), listener);
}
handler->Connect(self_attr.id(), listener);
class ListenerHandler
template <typename MessageT>
void ListenerHandler<MessageT>::Connect(uint64_t self_id,
const Listener& listener) {
auto connection = signal_.Connect(listener);
if (!connection.IsConnected()) {
return;
}
WriteLockGuard<AtomicRWLock> lock(rw_lock_);
signal_conns_[self_id] = connection;
}
auto connection = signal_.Connect(listener);
class Signal
ConnectionType Connect(const Callback& cb) {
auto slot = std::make_shared<Slot<Args...>>(cb);
{
std::lock_guard<std::mutex> lock(mutex_);
slots_.emplace_back(slot);
}
return ConnectionType(slot, this);
}
ConnectionType(slot, this);
class Connection 构造函数
Connection(const SlotPtr& slot, const SignalPtr& signal)
: slot_(slot), signal_(signal) {}
ShmDispatcher中ThreadFunc()线程一直运行
class ShmDispatcher
void ShmDispatcher::ThreadFunc() {
ReadableInfo readable_info;
while (!is_shutdown_.load()) {
if (!notifier_->Listen(100, &readable_info)) {
ADEBUG << "listen failed.";
continue;
}
uint64_t host_id = readable_info.host_id();
if (host_id != host_id_) {
ADEBUG << "shm readable info from other host.";
continue;
}
uint64_t channel_id = readable_info.channel_id();
uint32_t block_index = readable_info.block_index();
{
ReadLockGuard<AtomicRWLock> lock(segments_lock_);
if (segments_.count(channel_id) == 0) {
continue;
}
// check block index
if (previous_indexes_.count(channel_id) == 0) {
previous_indexes_[channel_id] = UINT32_MAX;
}
uint32_t& previous_index = previous_indexes_[channel_id];
if (block_index != 0 && previous_index != UINT32_MAX) {
if (block_index == previous_index) {
ADEBUG << "Receive SAME index " << block_index << " of channel "
<< channel_id;
} else if (block_index < previous_index) {
ADEBUG << "Receive PREVIOUS message. last: " << previous_index
<< ", now: " << block_index;
} else if (block_index - previous_index > 1) {
ADEBUG << "Receive JUMP message. last: " << previous_index
<< ", now: " << block_index;
}
}
previous_index = block_index;
ReadMessage(channel_id, block_index);
}
}
}
if (!notifier_->Listen(100, &readable_info)) {
ADEBUG << “listen failed.”;
continue;
}
class ConditionNotifier
bool ConditionNotifier::Listen(int timeout_ms, ReadableInfo* info) {
if (info == nullptr) {
AERROR << "info nullptr.";
return false;
}
if (is_shutdown_.load()) {
ADEBUG << "notifier is shutdown.";
return false;
}
std::unique_lock<std::mutex> lck(indicator_->mtx);
if (next_listen_num_ >= indicator_->written_info_num) {
uint64_t target = next_listen_num_;
if (!indicator_->cv.wait_for(
lck, std::chrono::milliseconds(timeout_ms), [target, this]() {
return this->indicator_->written_info_num > target ||
this->is_shutdown_.load();
})) {
ADEBUG << "timeout";
return false;
}
if (is_shutdown_.load()) {
AINFO << "notifier is shutdown.";
return false;
}
}
if (next_listen_num_ == 0) {
next_listen_num_ = indicator_->written_info_num - 1;
}
auto idx = next_listen_num_ % kBufLength;
*info = indicator_->infos[idx];
next_listen_num_ += 1;
return true;
}
ReadMessage(channel_id, block_index);
class ShmDispatcher
void ShmDispatcher::ReadMessage(uint64_t channel_id, uint32_t block_index) {
ADEBUG << "Reading sharedmem message: "
<< GlobalData::GetChannelById(channel_id)
<< " from block: " << block_index;
auto rb = std::make_shared<ReadableBlock>();
rb->index = block_index;
if (!segments_[channel_id]->AcquireBlockToRead(rb.get())) {
AWARN << "fail to acquire block, channel: "
<< GlobalData::GetChannelById(channel_id)
<< " index: " << block_index;
return;
}
MessageInfo msg_info;
const char* msg_info_addr =
reinterpret_cast<char*>(rb->buf) + rb->block->msg_size();
if (msg_info.DeserializeFrom(msg_info_addr, rb->block->msg_info_size())) {
OnMessage(channel_id, rb, msg_info);
} else {
AERROR << "error msg info of channel:"
<< GlobalData::GetChannelById(channel_id);
}
segments_[channel_id]->ReleaseReadBlock(*rb);
}
OnMessage(channel_id, rb, msg_info);
class ShrmDispatcher
void ShmDispatcher::OnMessage(uint64_t channel_id,
const std::shared_ptr<ReadableBlock>& rb,
const MessageInfo& msg_info) {
if (is_shutdown_.load()) {
return;
}
ListenerHandlerBasePtr* handler_base = nullptr;
if (msg_listeners_.Get(channel_id, &handler_base)) {
auto handler = std::dynamic_pointer_cast<ListenerHandler<ReadableBlock>>(
*handler_base);
handler->Run(rb, msg_info);
} else {
AERROR << "Cant find " << GlobalData::GetChannelById(channel_id)
<< "'s handler.";
}
}
handler->Run(rb, msg_info);
class ListenerHandler
template <typename MessageT> //Message :
void ListenerHandler<MessageT>::Run(const Message& msg,
const MessageInfo& msg_info) {
signal_(msg, msg_info);
uint64_t oppo_id = msg_info.sender_id().HashValue();
ReadLockGuard<AtomicRWLock> lock(rw_lock_);
if (signals_.find(oppo_id) == signals_.end()) {
return;
}
(*signals_[oppo_id])(msg, msg_info);
}
(*signals_[oppo_id])(msg, msg_info)
class Signal
void operator()(Args... args) {
SlotList local;
{
std::lock_guard<std::mutex> lock(mutex_);
for (auto& slot : slots_) {
local.emplace_back(slot);
}
}
if (!local.empty()) {
for (auto& slot : local) {
(*slot)(args...);
}
}
ClearDisconnectedSlots();
}
if (!local.empty()) {
for (auto& slot : local) {
(*slot)(args…);
}
}
class Slot
void operator()(Args... args) {
if (connected_ && cb_) {
cb_(args...);
}
}
/*
// cb_(args...);
auto listener_adapter = [listener](const std::shared_ptr<ReadableBlock>& rb,
const MessageInfo& msg_info) {
auto msg = std::make_shared<MessageT>();
RETURN_IF(!message::ParseFromArray(
rb->buf, static_cast<int>(rb->block->msg_size()), msg.get()));
listener(msg, msg_info);
};
//
listener=ShmReceiver<M>::OnNewMessage
*/
if (connected_ && cb_) {
cb_(args…); //msg, msg_info
}
class ShmDispatcher
auto listener_adapter = [listener](const std::shared_ptr<ReadableBlock>& rb,
const MessageInfo& msg_info) {
auto msg = std::make_shared<MessageT>();
RETURN_IF(!message::ParseFromArray(
rb->buf, static_cast<int>(rb->block->msg_size()), msg.get()));
listener(msg, msg_info);
//listener=ShmReceiver<M>::OnNewMessage
};
class Receiver
template <typename M>
void Receiver<M>::OnNewMessage(const MessagePtr& msg,
const MessageInfo& msg_info) {
if (msg_listener_ != nullptr) {
msg_listener_(msg, msg_info, attr_);
}
}
msg_listener_ (msg, msg_info, attr_);
class ReceiverManager
template <typename MessageT>
auto ReceiverManager<MessageT>::GetReceiver函数中
[](const std::shared_ptr<MessageT>& msg,
const transport::MessageInfo& msg_info,
const proto::RoleAttributes& reader_attr) {
(void)msg_info;
(void)reader_attr;
PerfEventCache::Instance()->AddTransportEvent(
TransPerf::TRANS_TO, reader_attr.channel_id(),
msg_info.seq_num());
data::DataDispatcher<MessageT>::Instance()->Dispatch(
reader_attr.channel_id(), msg);
PerfEventCache::Instance()->AddTransportEvent(
TransPerf::WRITE_NOTIFY, reader_attr.channel_id(),
msg_info.seq_num());
}
data::DataDispatcher::Instance()->Dispatch(
reader_attr.channel_id(), msg);
class DataDispatcher
template <typename T>
bool DataDispatcher<T>::Dispatch(const uint64_t channel_id,
const std::shared_ptr<T>& msg) {
BufferVector* buffers = nullptr;
if (apollo::cyber::IsShutdown()) {
return false;
}
if (buffers_map_.Get(channel_id, &buffers)) {
for (auto& buffer_wptr : *buffers) {
if (auto buffer = buffer_wptr.lock()) {
std::lock_guard<std::mutex> lock(buffer->Mutex());
buffer->Fill(msg);
}
}
} else {
return false;
}
return notifier_->Notify(channel_id);
}
/*
template <typename M0>//DataVisito构造函数
class DataVisitor<M0, NullType, NullType, NullType> : public DataVisitorBase
DataVisitor(uint64_t channel_id, uint32_t queue_size)
: buffer_(channel_id, new BufferType<M0>(queue_size)) {
DataDispatcher<M0>::Instance()->AddBuffer(buffer_);
data_notifier_->AddNotifier(buffer_.channel_id(), notifier_);
}
*/