muduo Dispatcher消息分发器 通过多态和模板进行向上类型转换

时间:2022-07-26
本文章向大家介绍muduo Dispatcher消息分发器 通过多态和模板进行向上类型转换,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

所谓消息分发(muduo 中,就是接收到buffer之后,额,或者说是 protobuf),在简单的程序设计里面的话,估计就是 type-switch 了,但是这样的话,肯定就不好扩展维护啦。

最后的方法就是,可以根据 type-name 自动去调用相应的方法。

typedef boost::function<void (Message*)> ProtobufMessageCallback;

这个算是一个映射咯。muduo 中采用的是 map<Descriptor*,ProtobufMessageCallback>,使用前,先注册,注册了就有相应的方法可以调用了。

muduo 中就提出了一个要求,要求回调之后,用户不需要自己再做类型转换的事情;

比如

QueryServer::onLogin(Message *){

  Login * pL = dynaminc_cast<Login *>(pMsg); //这里就用户要自己调用类型转换

}

//智能指针要用 boost::shared_ptr<DeriveClass> ptrDerive = boost::dynamic_pointer_cast<DeriveClass>(ptrBase);

// 来进行向上类型转换。

于是 muduo 就采用 多态+模板的方法,这样,用户只需要在 dispatcher 中注册相应的具体类型的回调函数就可以了。

typedef boost::shared_ptr<google::protobuf::Message> MessagePtr;

class Callback : boost::noncopyable
{
 public:
  virtual ~Callback() {};
  virtual void onMessage(const muduo::net::TcpConnectionPtr&,
                         const MessagePtr& message,
                         muduo::Timestamp) const = 0;
};

template <typename T>
class CallbackT : public Callback
{
#ifndef NDEBUG
  BOOST_STATIC_ASSERT((boost::is_base_of<google::protobuf::Message, T>::value));
#endif
 public:
  typedef boost::function<void (const muduo::net::TcpConnectionPtr&,
                                const boost::shared_ptr<T>& message,
                                muduo::Timestamp)> ProtobufMessageTCallback;

  CallbackT(const ProtobufMessageTCallback& callback)
    : callback_(callback)
  {
  }

  virtual void onMessage(const muduo::net::TcpConnectionPtr& conn,
                         const MessagePtr& message,
                         muduo::Timestamp receiveTime) const
  {
    boost::shared_ptr<T> concrete = muduo::down_pointer_cast<T>(message);//消息类型转换
    assert(concrete != NULL);
    callback_(conn, concrete, receiveTime);//调用回调
  }

 private:
  ProtobufMessageTCallback callback_;
};

再一个模板注册函数

template<typename T>
  void registerMessageCallback(const typename CallbackT<T>::ProtobufMessageTCallback& callback)
  {
    boost::shared_ptr<CallbackT<T> > pd(new CallbackT<T>(callback));//根据回调生成相应的function
    callbacks_[T::descriptor()] = pd;//注册,也就是使用map村粗
  }