zoukankan      html  css  js  c++  java
  • SRS源码—— Thread笔记

    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? 1:0), 0)) == 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 < 0) {
                st_usleep(10 * 1000);
            }
            
            // 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(10 * 1000);
            }
            
            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 != 0) {
                    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() = 0;
    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 这两个接口函数都一样,但是并没有继承关系。

  • 相关阅读:
    PAT1001
    关于yahoo.com.cn邮箱导入Gmail邮箱验证异常的机制解析及解决办法
    浙大机试感受
    PAT1002
    mysql修改密码后无法登陆问题
    Windows 不能在 本地计算机 启动 OracleDBConsoleorcl
    Deprecated: Function ereg_replace() is deprecated
    PHP中静态方法(static)与非静态方法的使用及区别
    微信小程序开发,weui报“渲染层错误”的解决办法
    Android系统下载管理DownloadManager功能介绍及使用示例
  • 原文地址:https://www.cnblogs.com/zoneofmine/p/10890687.html
Copyright © 2011-2022 走看看