x265-1.7版本-common/threadpool.h注释

注:问号以及未注释部分 会在x265-1.8版本内更新

/*****************************************************************************
 * Copyright (C) 2013 x265 project
 *
 * Authors: Steve Borho 
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
 *
 * This program is also available under a commercial proprietary license.
 * For more information, contact us at license @ x265.com
 *****************************************************************************/

#ifndef X265_THREADPOOL_H
#define X265_THREADPOOL_H

#include "common.h"
#include "threading.h"

namespace x265 {
// x265 private namespace

class ThreadPool;
class WorkerThread;
class BondedTaskGroup;

#if X86_64
typedef uint64_t sleepbitmap_t;
#else
typedef uint32_t sleepbitmap_t;
#endif

static const sleepbitmap_t ALL_POOL_THREADS = (sleepbitmap_t)-1;
enum { MAX_POOL_THREADS = sizeof(sleepbitmap_t) * 8 };
enum { INVALID_SLICE_PRIORITY = 10 }; // a value larger than any X265_TYPE_* macro

// Frame level job providers. FrameEncoder and Lookahead derive from
// this class and implement findJob()
class JobProvider
{
public:

    ThreadPool*   m_pool;        //指向encoder类中的m_threadPool
    sleepbitmap_t m_ownerBitmap; //当前任务拥有的核
                                 //ALL_POOL_THREADS =  -1   sleepbitmap_t 为无符号数64位整数,初始化为0
                                 //这是一个map,如4核机器:cup(0,1,2,3) 对应 (1,10,100,1000),查看当前哪些位置是1表示当前哪个cpu在干活,如果是4核,最大值当然就是1111,15
                                 //在函数JobProvider::tryWakeOne()和WorkerThread::threadMain()会对其改变 在tryWakeOne()中,将释放当前其不应该拥有的id,重新更新map
    int           m_jpId;        //其对应的jobid,一个任务一个id如:4核单机中:m_frameEncoder[0]  m_jpId:0  m_frameEncoder[1]  m_jpId:1  m_lookahead m_jpId:2

    int           m_sliceType;   //???在FrameEncoder类中表示其帧类型
    bool          m_helpWanted;  //初始化为false,会在JobProvider::tryWakeOne()、WaveFront::findJob(int threadId)、 Lookahead::findJob()中有更新  
                                 //Lookahead::findJob()中:如果当前还不能进行帧类型决策,则将其置为false,表示暂不需要核 
                                 //JobProvider::tryWakeOne() 中,如果当前没有返回可用的mid(核),则置为true,表示需要核
                                 //WaveFront::findJob(int threadId)???
    bool          m_isFrameEncoder; // 当前子类是否是FrameEncoder,在创建子类FrameEencoder时候会对该值进行赋值/* rather ugly hack, but nothing better presents itself */

    JobProvider()
        : m_pool(NULL)
        , m_ownerBitmap(0)
        , m_jpId(-1)
        , m_sliceType(INVALID_SLICE_PRIORITY)
        , m_helpWanted(false)
        , m_isFrameEncoder(false)
    {}

    virtual ~JobProvider() {}

    // Worker threads will call this method to perform work
    virtual void findJob(int workerThreadId) = 0;

    // Will awaken one idle thread, preferring a thread which most recently
    // performed work for this provider.
    void tryWakeOne();
};

class ThreadPool
{
public:

    sleepbitmap_t m_sleepBitmap;//  用于记录当前哪些核是sleep,其对应位为1的 ,一开始拥有全部的全部为sleep  (例如四核机器:一般是0~15的数据) 
                                //  在函数tryAcquireSleepingThread 和WorkerThread::threadMain()会对其改变
    int           m_numProviders;//当前提供给几个线程 如: 0 frameEncode[0]  1 frameEncoder[1]  2 lookachead
    int           m_numWorkers;//当前机器核数  单机4核测试是4
    int           m_numaNode;
    bool          m_isActive;

    JobProvider** m_jpTable;
    WorkerThread* m_workers;

    ThreadPool();
    ~ThreadPool();

    bool create(int numThreads, int maxProviders, int node);
    bool start();
    void stopWorkers();
    /** 函数功能             :设置线程间能够在不同的核运行,而不会同时占用同一个核
    /*  调用范围             :只在 WorkerThread::threadMain()和FrameEncoder::threadMain()函数中被调用
    * \参数 numaNode         :表示当前处于node的位置,如果没有配置,则只有一个就是0
    * \返回                  :null * */
    void setCurrentThreadAffinity();
    /** 函数功能             :在tryWakeOne中返回当前机器任意一个正在睡眠的核,tryBondPeers返回当前线程拥有核且正在睡眠的核
    /*  调用范围             :只在 JobProvider::tryWakeOne()和ThreadPool::tryBondPeers函数中被调用
    * \参数 firstTryBitmap   :为Job的m_ownerBitmap (如4核机器:一般传入是-1~15的数据)
    * \参数 secondTryBitmap  :只有0 和 -1 两个值能够传进来,tryBondPeers为0 tryWakeOne() 为-1(全为1,mask值)
    * \返回                  :在tryWakeOne中返回当前机器任意一个正在睡眠的核,tryBondPeers返回当前线程拥有核且正在睡眠的核 * */
    int  tryAcquireSleepingThread(sleepbitmap_t firstTryBitmap, sleepbitmap_t secondTryBitmap);
    /** 函数功能             : 返回当前可用核数,并在threadmain中触发相应processtask
    /*  调用范围             : 只在slicetypeDecide、CostEstimateGroup::finishBatch()、CostEstimateGroup::estimateFrameCost、predInterSearch、compressFrame()和compressInterCU_dist函数中被调用
    * \返回                  : 返回当前可用核数 * */
    int  tryBondPeers(int maxPeers, sleepbitmap_t peerBitmap, BondedTaskGroup& master);

    static ThreadPool* allocThreadPools(x265_param* p, int& numPools);

    static int  getCpuCount();
    static int  getNumaNodeCount();
    /** 函数功能             :设置线程间能够在不同的核运行,而不会同时占用同一个核
    /*  调用范围             :只在 ThreadPool::setCurrentThreadAffinity()函数中被调用
    * \参数 numaNode         :表示当前处于node的位置,如果没有配置,则只有一个就是0
    * \返回                  :null * */
    static void setThreadNodeAffinity(int node);
};

/* Any worker thread may enlist the help of idle worker threads from the same
 * job provider. They must derive from this class and implement the
 * processTasks() method.  To use, an instance must be instantiated by a worker
 * thread (referred to as the master thread) and then tryBondPeers() must be
 * called. If it returns non-zero then some number of slave worker threads are
 * already in the process of calling your processTasks() function. The master
 * thread should participate and call processTasks() itself. When
 * waitForExit() returns, all bonded peer threads are quarunteed to have
 * exitied processTasks(). Since the thread count is small, it uses explicit
 * locking instead of atomic counters and bitmasks */
class BondedTaskGroup //被PMODE、WeightAnalysis、PME、CostEstimateGroup、PreLookaheadGroup继承
{
public:

    Lock              m_lock;            //在多线程操作中获取临界资源时用于加锁
    ThreadSafeInteger m_exitedPeerCount; //加锁计数参量,每当完成一个任务自加1,初始化为0
    int               m_bondedPeerCount; //计算当前任务拥有多少核
    int               m_jobTotal;        //当前需要运行的任务总数: 如在PreLookaheadGroup子类中表示当前有多少帧没有初始化(lookachead)
                                         //CostEstimateGroup子类中表示当前有多少需要计算frame-cost的帧数 1.  2. lookachead 多slice配置中:一帧有多少slice
                                         //????
    int               m_jobAcquired;     //计数当前已经完成的任务数目

    BondedTaskGroup()  { m_bondedPeerCount = m_jobTotal = m_jobAcquired = 0; }//初始化

    /* Do not allow the instance to be destroyed before all bonded peers have
     * exited processTasks() */
    ~BondedTaskGroup() { waitForExit(); }//等待全部任务完成,释放内存

    /* Try to enlist the help of idle worker threads on most recently associated
     * with the given job provider and "bond" them to work on your tasks. Up to
     * maxPeers worker threads will call your processTasks() method. */
    /** 函数功能             : 返回当前可用核数,并在threadmain中触发相应processtask,从当前job中拥有核并且sleep状态的核才可以触发
    /*  调用范围             : 只在Analysis::compressInterCU_dist、FrameEncoder::compressFrame()、Search::predInterSearch函数中被调用
    * \返回                  : 返回当前可用核数 * */
    int tryBondPeers(JobProvider& jp, int maxPeers)
    {
        int count = jp.m_pool->tryBondPeers(maxPeers, jp.m_ownerBitmap, *this);
        m_bondedPeerCount += count;
        return count;
    }

    /* Try to enlist the help of any idle worker threads and "bond" them to work
     * on your tasks. Up to maxPeers worker threads will call your
     * processTasks() method. */
    /** 函数功能             : 返回当前可用核数,并在threadmain中触发相应processtask,只要是sleep状态的核都可以触发
    /*  调用范围             : 只在slicetypeDecide、CostEstimateGroup::finishBatch()、CostEstimateGroup::estimateFrameCost函数中被调用
    * \返回                  : 返回当前可用核数 * */
    int tryBondPeers(ThreadPool& pool, int maxPeers)
    {
        int count = pool.tryBondPeers(maxPeers, ALL_POOL_THREADS, *this);
        m_bondedPeerCount += count;
        return count;
    }

    /* Returns when all bonded peers have exited processTasks(). It does *NOT*
     * ensure all tasks are completed (but this is generally implied). */
    /** 函数功能             : 一直等待到任务全部完成,这里等待的是核释放,内核释放了任务也就完成了
    /*  调用范围             : 只在compressInterCU_dist、compressFrame()、predInterSearch、slicetypeDecide()、CostEstimateGroup::finishBatch()、CostEstimateGroup::estimateFrameCost函数中被调用
    * \返回                  : null * */
    void waitForExit()
    {
        int exited = m_exitedPeerCount.get();
        while (m_bondedPeerCount != exited)  //如果在threadmain释放的核数等于当前拥有的核数说明当前已经完成任务
            exited = m_exitedPeerCount.waitForChange(exited);
    }

    /* Derived classes must define this method. The worker thread ID may be
     * used to index into thread local data, or ignored.  The ID will be between
     * 0 and jp.m_numWorkers - 1 */
    //虚函数,具体运行其子类的task
    virtual void processTasks(int workerThreadId) = 0;
};

} // end namespace x265

#endif // ifndef X265_THREADPOOL_H


 

你可能感兴趣的:(x265代码注释)