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

来源:互联网 发布:c语言调用linux命令 编辑:程序博客网 时间:2024/06/15 15:27

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

/***************************************************************************** * Copyright (C) 2013 x265 project * * Authors: Steve Borho <steve@borho.org> * * 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 namespaceclass ThreadPool;class WorkerThread;class BondedTaskGroup;#if X86_64typedef uint64_t sleepbitmap_t;#elsetypedef uint32_t sleepbitmap_t;#endifstatic 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


 

1 0