SRS源码中的Thread是一层套一层,最终的Thread类是在 srs_app_thread.cpp 的 SrsThread

这里我们暂且先放下协程的概念,把它当线程来看,其逻辑如下:

1. 在start() 方法中创建线程:

 int SrsThread::start()
{
int ret = ERROR_SUCCESS; if(tid) {
srs_info("thread %s already running.", _name);
return ret;
} if((tid = st_thread_create(thread_fun, this, (_joinable? :), )) == NULL){
ret = ERROR_ST_CREATE_CYCLE_THREAD;
srs_error("st_thread_create failed. ret=%d", ret);
return ret;
} disposed = false;
// we set to loop to true for thread to run.
loop = true; // wait for cid to ready, for parent thread to get the cid.
while (_cid < ) {
st_usleep( * );
} // now, cycle thread can run.
can_run = true; return ret;
}

2. 执行的函数是 thread_fun,参数是其本身即: this,再实际调用 this->thread_cycle()

void* SrsThread::thread_fun(void* arg)
{
SrsThread* obj = (SrsThread*)arg;
srs_assert(obj); obj->thread_cycle(); // for valgrind to detect.
SrsThreadContext* ctx = dynamic_cast<SrsThreadContext*>(_srs_context);
if (ctx) {
ctx->clear_cid();
} st_thread_exit(NULL); return NULL;
}

3. thread_cycle() 实现如下:

void SrsThread::thread_cycle()
{
int ret = ERROR_SUCCESS; _srs_context->generate_id();
srs_info("thread %s cycle start", _name); _cid = _srs_context->get_id(); srs_assert(handler);
handler->on_thread_start(); // thread is running now.
really_terminated = false; // wait for cid to ready, for parent thread to get the cid.
while (!can_run && loop) {
st_usleep( * );
} while (loop) {
if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) {
srs_warn("thread %s on before cycle failed, ignored and retry, ret=%d", _name, ret);
goto failed;
}
srs_info("thread %s on before cycle success", _name); if ((ret = handler->cycle()) != ERROR_SUCCESS) {
if (!srs_is_client_gracefully_close(ret) && !srs_is_system_control_error(ret)) {
srs_warn("thread %s cycle failed, ignored and retry, ret=%d", _name, ret);
}
goto failed;
}
srs_info("thread %s cycle success", _name); if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) {
srs_warn("thread %s on end cycle failed, ignored and retry, ret=%d", _name, ret);
goto failed;
}
srs_info("thread %s on end cycle success", _name); failed:
if (!loop) {
break;
} // to improve performance, donot sleep when interval is zero.
// @see: https://github.com/ossrs/srs/issues/237
if (cycle_interval_us != ) {
st_usleep(cycle_interval_us);
}
} // readly terminated now.
really_terminated = true; handler->on_thread_stop();
srs_info("thread %s cycle finished", _name);
}

其核心就是循环调用 变量 ISrsThreadHandler* handler (构造函数的参数赋值进来的)如下三个函数:

virtual int on_before_cycle();
virtual int cycle() = ;
virtual int on_end_cycle();

4. 停止线程循环可以调用 stop_loop() :

void SrsThread::stop_loop()
{
loop = false;
}

但是仔细看使用线程的代码会发现,ISrsThreadHandler* handler 这个变量还是被封装了。

如 SrsOneCycleThread 自己继承自 ISrsThreadHandler

class SrsOneCycleThread : public internal::ISrsThreadHandler
{
private:
internal::SrsThread* pthread;
ISrsOneCycleThreadHandler* handler; //...
}

在new SrsThread 时,将自己的this指针传入,当作SrsThread 的 handler变量,

然后自己的线程函数中重新调用自己的变量: ISrsOneCycleThreadHandler* handler

int SrsOneCycleThread::cycle()
{
int ret = handler->cycle();
pthread->stop_loop();
return ret;
} void SrsOneCycleThread::on_thread_start()
{
handler->on_thread_start();
} int SrsOneCycleThread::on_before_cycle()
{
return handler->on_before_cycle();
} int SrsOneCycleThread::on_end_cycle()
{
return handler->on_end_cycle();
} void SrsOneCycleThread::on_thread_stop()
{
handler->on_thread_stop();
}

注意,虽然 ISrsOneCycleThreadHandlerISrsThreadHandler 这两个接口函数都一样,但是并没有继承关系。

SRS源码—— Thread笔记的更多相关文章

  1. zeromq源码分析笔记之线程间收发命令(2)

    在zeromq源码分析笔记之架构说到了zmq的整体架构,可以看到线程间通信包括两类,一类是用于收发命令,告知对象该调用什么方法去做什么事情,命令的结构由command_t结构体确定:另一类是socke ...

  2. AQS源码阅读笔记(一)

    AQS源码阅读笔记 先看下这个类张非常重要的一个静态内部类Node.如下: static final class Node { //表示当前节点以共享模式等待锁 static final Node S ...

  3. Mina源码阅读笔记(四)—Mina的连接IoConnector2

    接着Mina源码阅读笔记(四)-Mina的连接IoConnector1,,我们继续: AbstractIoAcceptor: 001 package org.apache.mina.core.rewr ...

  4. Hadoop源码学习笔记(4) ——Socket到RPC调用

    Hadoop源码学习笔记(4) ——Socket到RPC调用 Hadoop是一个分布式程序,分布在多台机器上运行,事必会涉及到网络编程.那这里如何让网络编程变得简单.透明的呢? 网络编程中,首先我们要 ...

  5. Hadoop源码学习笔记(3) ——初览DataNode及学习线程

    Hadoop源码学习笔记(3) ——初览DataNode及学习线程 进入了main函数,我们走出了第一步,接下来看看再怎么走: public class DataNode extends Config ...

  6. Hadoop源码学习笔记(2) ——进入main函数打印包信息

    Hadoop源码学习笔记(2) ——进入main函数打印包信息 找到了main函数,也建立了快速启动的方法,然后我们就进去看一看. 进入NameNode和DataNode的主函数后,发现形式差不多: ...

  7. RocketMQ 源码学习笔记————Producer 是怎么将消息发送至 Broker 的?

    目录 RocketMQ 源码学习笔记----Producer 是怎么将消息发送至 Broker 的? 前言 项目结构 rocketmq-client 模块 DefaultMQProducerTest ...

  8. RocketMQ 源码学习笔记 Producer 是怎么将消息发送至 Broker 的?

    目录 RocketMQ 源码学习笔记 Producer 是怎么将消息发送至 Broker 的? 前言 项目结构 rocketmq-client 模块 DefaultMQProducerTest Roc ...

  9. ReentrantReadWriteLock源码分析笔记

    ReentrantReadWriteLock包含两把锁,一是读锁ReadLock, 此乃共享锁, 一是写锁WriteLock, 此乃排它锁. 这两把锁都是基于AQS来实现的. 下面通过源码来看看Ree ...

随机推荐

  1. 解决新版Pycharm中Matplotlib图像不在弹出独立的显示窗口问题

    官方说明链接: https://intellij-support.jetbrains.com/hc/en-us/community/posts/115000736584-SciView-in-PyCh ...

  2. tkinter学习(4)frame、pack、canvas学习

    1.frame和pack学习 1.1 代码: import tkinter as tk window = tk.Tk() window.title('my window') window.geomet ...

  3. if语句的汇编表示

    转自:https://blog.csdn.net/u011608357/article/details/22586137 demo: C语言: int max(int x,int y) { if (x ...

  4. 微信-获取openid

    第一步 首先把微信的支付流程与相关的文档熟悉一遍,具体的支付逻辑是怎么实现的,心里要有一定的路数,开发的时候一边看文档,一边写,再一边调试这是最好的选择,首先阅读微信开发文档,因为我们这次是做公众号支 ...

  5. 解决STM32工程出现:Undefined symbol TIM_ClearFlag (referred from hcsr04.o).错误。类型问题Undefined symbol TIM_xxx (referred from xxx.o).

    出错原因: 工程FWLIB目录下没有添加stm32f10x_tim.c文件. 添加即可. 一般利用库开发,将ppp.c(ppp.c又调用了库stm32f10x_xx.h)写好之后的调用步骤: 举例使用 ...

  6. Java日期时间API系列19-----Jdk8中java.time包中的新的日期时间API类,ZonedDateTime与ZoneId和LocalDateTime的关系,ZonedDateTime格式化和时区转换等。

    通过Java日期时间API系列6-----Jdk8中java.time包中的新的日期时间API类中时间范围示意图:可以很清晰的看出ZonedDateTime相当于LocalDateTime+ZoneI ...

  7. linux理论知识点(用于考试)

    ps:为其十天左右的linux培训即将结束了,未雨绸缪,为了更好的通过之后的考试,提前多看些考试题和知识点.这是在chinaunix论坛看到的一个帖子,贴来分享. 原文地址:[http://bbs.c ...

  8. 为 git 设定 socks5 代理

    为 git 设定 socks5 代理 查看当前设定 git config --global -l 为 git 设定全局代理 git config --global http.proxy socks5h ...

  9. 【代码学习】PYHTON 元组

    Python的元组与列表类似,不同之处在于元组的元素不能修改.也可进行分片 和 连接操作. 元组使用小括号,列表使用方括号. 一.访问元组 #coding=utf-8 Tuple = ('name', ...

  10. PyQt5剪切板操作

    1.使用剪切板import sys,mathfrom PyQt5.QtWidgets import *from PyQt5.QtGui import *from PyQt5.QtCore import ...