c++スレッドプールprogschj/threadPool解析

3392 ワード

ソースコード
https://github.com/progschj/ThreadPool.git
これはc++11バージョン以上に適応したスレッドプール実装であり,std::futureなどの新機能を用いることでタスクの戻り値を得ることができる各種スレッドタスクを追加できる.githubに3.2 kのstarがあります.
最後に疑問があって、大物に困惑を解くことを求めます(すでに理解して、タスクを切り替えるのはいつ行うのではありませんて、もし前のタスクが進行しているならば、コードはtask()で実行して、この時タスクを切り替えることはできません)
スレッドプールの雛形
c++スレッドプールには比較的基本的なモデルがあり、いくつかのプロジェクトを見て、それらの基本的な構造がこのブログから理解できることを発見しました.
https://www.cnblogs.com/ailumiyana/p/10016965.html
スレッドプールの原理を簡単に述べる
スレッドプールは、通常、クラスThreadPoolとして実装されます.このクラスには主に4つの機能があります.
1.スレッドプールマネージャ(現在のアイドルプロセスにキューを取るヘッダタスクを実行させるコンストラクション関数;コンストラクション関数、スレッドの終了を待つ)
2.作業スレッド(vector)
3.タスクインタフェース(addTaskまたはenqueue)
4.タスクキュー(一般的にqueue)
キー:
1.スレッドプールを確立する時、一定数のスレッドを指定して、開く.各スレッドのタスクはキューが空でなく、現在タスクを実行していない時、タスクを取って実行する(条件反発量で実現する)
2.タスクが来るたびに、タスクキューに格納され、各スレッドに通知される(条件反発量によって実現される)
 
関連するc++11特性
1.匿名関数の方が簡単
2.可変テンプレートパラメータ
3. std::bind  
4. std::future、std::packaged_task
5. std::function
-235がポイントです.std::functionは関数ポインタに使用できます.std::function+std::bindはfunction宣言時とは異なる関数を結合することができます.
-std::bind+可変パラメータテンプレートは、任意の関数をfunctionにバインドすることができます.
例:
template
int push(F&& f, Args&&... args)
{
    std::function task;
    task = std::bind(f, args...);
    task();
    return 1;
}

std::futureはスレッド関数を取得するための戻り値でありget()メソッドで実現できる.
コード#コード#
コードは全部で2つの部分に分かれています.hとexample.cpp.c++の特性はいくつかありますが、ほとんど重要ではない特性を無視することができます(forward)
ThreadPool.h中部分解釈:
// the constructor just launches some amount of workers
inline ThreadPool::ThreadPool(size_t threads)
    :   stop(false)
{
    for(size_t i = 0;i task;

                    {
                        std::unique_lock<:mutex> lock(this->queue_mutex);
                        this->condition.wait(lock,
                            [this]{ return this->stop || !this->tasks.empty(); });
                        if(this->stop && this->tasks.empty())
                            return;
                        task = std::move(this->tasks.front());
                        this->tasks.pop();
                    }
                    //   task           ,               
                    task();
                }
            }
        );
}

// add new work item to the pool
template
auto ThreadPool::enqueue(F&& f, Args&&... args) 
    -> std::future::type>
{
    using return_type = typename std::result_of::type;

    auto task = std::make_shared< std::packaged_task >(
            std::bind(std::forward(f), std::forward(args)...)
        );
        
    std::future res = task->get_future();
    {
        std::unique_lock<:mutex> lock(queue_mutex);

        // don't allow enqueueing after stopping the pool
        if(stop)
            throw std::runtime_error("enqueue on stopped ThreadPool");

        //                 ,          ,        。
        tasks.emplace([task](){ (*task)(); });
    }
    condition.notify_one();
    return res;
}


#endif