WebRTC 源码导读 101 · logging and checks

WebRTC 源码导读 000 · 目录

文中提到的代码引用自 libwebrtc M90 版本 https://github.com/aggresss/libwebrtc/tree/M90

日志和断言源文件位置:

└── src
    └── rtc_base
        ├── logging.cc
        ├── logging.h
        ├── checks.cc
        └── checks.h

通常来说中大型的工程都会自己造一些轮子,libwebrtc 也不例外。在 libwebrtc 的源码中出现频率最高的可能是 RTC_CHECK()RTC_LOG() ,类似于 assert()printf() 的功能,来看一下他们的定义:

#define RTC_LOG_FILE_LINE(sev, file, line)        \
  ::rtc::webrtc_logging_impl::LogCall() &         \
      ::rtc::webrtc_logging_impl::LogStreamer<>() \
          << ::rtc::webrtc_logging_impl::LogMetadata(file, line, sev)
          
#define RTC_LOG(sev)                        \
  !rtc::LogMessage::IsNoop<::rtc::sev>() && \
      RTC_LOG_FILE_LINE(::rtc::sev, __FILE__, __LINE__)
#if RTC_CHECK_MSG_ENABLED
#define RTC_CHECK(condition)                                    \
  (condition) ? static_cast<void>(0)                            \
              : ::rtc::webrtc_checks_impl::FatalLogCall<false>( \
                    __FILE__, __LINE__, #condition) &           \
                    ::rtc::webrtc_checks_impl::LogStreamer<>()

LogStreamer 为了适配泛型参数使用了 C++11 的 Parameter Pack 特性,增加了阅读难度,所以我们先将这部分拆解出去,假设 LogStreamer 的输入参数只有 std::string。简化 LogStreamer 的实现流程,只接受 std::string 类型参数,并且取消 << 操作符的递归操作,只是为了解释 LogStreamer 的工作原理,简化的 LogStreamer 示例如下:

#ifndef LOG_STREAMER_V1_H_
#define LOG_STREAMER_V1_H_

#include <iostream>
#include <string>

#define LOG_V1 \
    v1::LogCall(__FILE__, " LOG_V1 ") & v1::LogStreamer()

namespace v1 {

class LogStreamer {
   public:
    explicit LogStreamer(const char* arg = "")
        : log_(arg) {}

    LogStreamer operator<<(const char* arg) {
        this->log_.append(arg);
        return *this;
    }

    template <typename... U>
    void Call(U... args) const {
        (std::cout << ... << args) << this->log_ << std::endl;
    }

   private:
    std::string log_;
};

class LogCall final {
   public:
    LogCall(const char* file, const char* message)
        : file_(file), message_(message) {}

    void operator&(const LogStreamer& streamer) {
        streamer.Call(file_, message_);
    }

   private:
    const char* file_;
    const char* message_;
};

}  // namespace v1

#endif  // LOG_STREAMER_V1_H_
  • LogStreamer 通过重载 << 操作符将每一个需要输出的参数封装为 LogStreamer 后返回,因为 << 操作符的结合顺序是从左到右,所以所有通过 << 结合到一起的参会最后会成为一个由 LogStreamer 组成的逆序单向链表;
  • << 的优先级高于 &,所以 ::rtc::webrtc_logging_impl::LogCall() 重载 & 操作符后会将上面的 LogStreamer 组成的逆序单向链表作为参数进行输出,它的输出原理是遍历链表中的输出参数,通过模版递归,将链表中的输出参数转化为自己的可变参数,最后通过 cstdargfprintf 将输出参数输出。

参考文档

  1. WebRTC日志功能解读 · 西当太白有鸟道 · 知乎
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值