接收消息

接收消息

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_);
      }
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海洋2416

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值