WebRTCWebRTC源码分析

WebRTC源码分析-线程基础之Message && Messa

2019-11-15  本文已影响0人  ice_ly000

前言

本文将介绍消息循环中的消息(Message),消息中持有的数据(MessageData),处理消息的Handler(MessageHandler)的基本内容。

其中Message与MessageData相关的结构体位于rtc_base/message_queue.h中,MessageHandler相关的类位于rtc_base/message_handler.h中

消息Message

WebRTC中消息相关的类分为两种,一种是Message,表征的是即时消息,投放到消息循环中期待能被立马消费;另外一种是DelayedMessage,表征的是延迟消息,投放到消息循环中不会立马被消费,而是延迟一段时间才会被消费。

Message 源码如下所示

struct Message {
  Message()
      : phandler(nullptr), message_id(0), pdata(nullptr), ts_sensitive(0) {}
  inline bool Match(MessageHandler* handler, uint32_t id) const {
    return (handler == nullptr || handler == phandler) &&
           (id == MQID_ANY || id == message_id);
  }
  Location posted_from;             // 消息自哪儿产生
  MessageHandler* phandler;    // 消息如何处理
  uint32_t message_id;              // 消息id
  MessageData* pdata;              // 消息中携带的数据
  int64_t ts_sensitive;                 // 消息产生的时间
};

Message结构体成员有如下几种:

Message结构体还提供了两个方法。

DelayedMessage源码如下

// DelayedMessage goes into a priority queue, sorted by trigger time.  Messages
// with the same trigger time are processed in num_ (FIFO) order.
class DelayedMessage {
 public:
  DelayedMessage(int64_t delay,
                 int64_t trigger,
                 uint32_t num,
                 const Message& msg)
      : cmsDelay_(delay), msTrigger_(trigger), num_(num), msg_(msg) {}

  bool operator<(const DelayedMessage& dmsg) const {
    return (dmsg.msTrigger_ < msTrigger_) ||
           ((dmsg.msTrigger_ == msTrigger_) && (dmsg.num_ < num_));
  }

  int64_t cmsDelay_;  // for debugging
  int64_t msTrigger_;
  uint32_t num_;
  Message msg_;
};

DelayedMessage与Message并非是继承is-a关系,而是has-a的关系。提供了除Message msg_成员之外的另几个成员:

由于DelayedMessage在MQ中会放至于专门的优先级队列中,优先级如何确定?DelayedMessage重载了小于"<"运算符以确定排序,先按消息需要被处理的触发时间戳msTrigger_排序;若触发时间相同,则按消息序号排序。当某个延迟消息要投放到延迟队列中时,该优先级队列会根据“<”运算符去比较这个延迟消息与队列中的消息以确定应在队列的哪个位置插入该消息。

MessageList被定义为std::list<Message>, MessageQueue中的即时消息就存储于MessageList类别的列表中,按照先入先出的方式挨个进行处理。

typedef std::list<Message> MessageList;

消息MessgeData

MessgeData 消息数据基类,其析构函数被定义为virtual类型,以防内存泄漏

class MessageData {
 public:
  MessageData() {}
  virtual ~MessageData() {}
};

TypedMessageData 使用模板定义的MessageData 的一个子类,便于扩展。

template <class T>
class TypedMessageData : public MessageData {
 public:
  explicit TypedMessageData(const T& data) : data_(data) {}
  const T& data() const { return data_; }
  T& data() { return data_; }
 private:
  T data_;
};

ScopedMessageData 类似于 TypedMessageData,用于指针类型。在析构函数中,自动对该指针调用 delete。

// Like TypedMessageData, but for pointers that require a delete.
template <class T>
class ScopedMessageData : public MessageData {
 public:
  explicit ScopedMessageData(std::unique_ptr<T> data)
      : data_(std::move(data)) {}
  // Deprecated.
  // TODO(deadbeef): Remove this once downstream applications stop using it.
  explicit ScopedMessageData(T* data) : data_(data) {}
  // Deprecated.
  // TODO(deadbeef): Returning a reference to a unique ptr? Why. Get rid of
  // this once downstream applications stop using it, then rename inner_data to
  // just data.
  const std::unique_ptr<T>& data() const { return data_; }
  std::unique_ptr<T>& data() { return data_; }

  const T& inner_data() const { return *data_; }
  T& inner_data() { return *data_; }

 private:
  std::unique_ptr<T> data_;
};

ScopedRefMessageData 类似于ScopedMessageData,用于引用计数的指针类型。

// Like ScopedMessageData, but for reference counted pointers.
template <class T>
class ScopedRefMessageData : public MessageData {
 public:
  explicit ScopedRefMessageData(T* data) : data_(data) {}
  const scoped_refptr<T>& data() const { return data_; }
  scoped_refptr<T>& data() { return data_; }

 private:
  scoped_refptr<T> data_;
};

DisposeData 这个值得注意下,和前面几个MessageData子类不一样,该对象并没有提供其内部数据data_的方法,那么该对象正如其名,持有需要进行销毁的数据。在哪些场景下使用?

template <class T>
class DisposeData : public MessageData {
 public:
  explicit DisposeData(T* data) : data_(data) {}
  virtual ~DisposeData() { delete data_; }

 private:
  T* data_;
};

WrapMessageData && UseMessageData 两个模板方法,分别用来将数据封装成MessageData以及取出对应的数据,封装拆箱操作。

template <class T>
inline MessageData* WrapMessageData(const T& data) {
  return new TypedMessageData<T>(data);
}

template <class T>
inline const T& UseMessageData(MessageData* data) {
  return static_cast<TypedMessageData<T>*>(data)->data();
}

消息处理器MessageHandler

MessageHandler 消息处理器的基类,子类在继承了该类之后要重载 OnMessage 函数,在其中实现消息响应的逻辑。

class MessageHandler {
 public:
  virtual ~MessageHandler();
  virtual void OnMessage(Message* msg) = 0;
 protected:
  MessageHandler() {}
 private:
  RTC_DISALLOW_COPY_AND_ASSIGN(MessageHandler);
};

FunctorMessageHandler MessageHandler的模板子类,用于帮助实现阻塞地跨线程在指定线程上执行某个方法,并可获取执行结果。Thread的Invoke()方法使用该类。该类的构造函数中使用了C++11的右值引用,转发语义std::forward,以及转移语义std::move。详见博客C++11 std::move和std::forward

// Helper class to facilitate executing a functor on a thread.
template <class ReturnT, class FunctorT>
class FunctorMessageHandler : public MessageHandler {
 public:
  explicit FunctorMessageHandler(FunctorT&& functor)
      : functor_(std::forward<FunctorT>(functor)) {}
  virtual void OnMessage(Message* msg) { result_ = functor_(); }
  const ReturnT& result() const { return result_; }
  // Returns moved result. Should not call result() or MoveResult() again
  // after this.
  ReturnT MoveResult() { return std::move(result_); }
 private:
  FunctorT functor_;
  ReturnT result_;
};

无返回值特例FunctorMessageHandler 返回值类型为 void 的函数的FunctorMessageHandler特化版本

// Specialization for ReturnT of void.
template <class FunctorT>
class FunctorMessageHandler<void, FunctorT> : public MessageHandler {
 public:
  explicit FunctorMessageHandler(FunctorT&& functor)
      : functor_(std::forward<FunctorT>(functor)) {}
  virtual void OnMessage(Message* msg) { functor_(); }
  void result() const {}
  void MoveResult() {}
 private:
  FunctorT functor_;
};

总结

至此,基本上将MQ相关的“边角料”介绍完毕了,重点的知识再回顾下:

上一篇 下一篇

猜你喜欢

热点阅读