首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++ STD线程池

C++ STD线程池
EN

Code Review用户
提问于 2017-09-11 04:32:39
回答 1查看 713关注 0票数 3

我想尝试实现我自己版本的C++线程池(我知道有很多..)。

我希望有人能知道我是否做得还好。

塔斯克h:

代码语言:javascript
复制
#pragma once

#include <memory>
#include <queue>
#include <thread>
#include <mutex>
#include <shared_mutex>
#include <condition_variable>

#include "../Worker/Worker.h"

class Tasker
{

public:

    //  Default Tasker Constructor.
    Tasker(const unsigned int & newTaskerThreadCount)
    {
        //  Construct the Vector of Threads. By default, each of these will not have any thread associated.
        mTaskerThreads = std::vector<std::thread>(newTaskerThreadCount);
    }


    //  Default Tasker Destructor, waits for all the workers to complete.
    virtual ~Tasker()
    {
        end();
    }


    //  Add Worker to the List of Workers to Execute.
    inline virtual void addWorker(std::shared_ptr<Worker> newWorker)
    {
        //  Create a unique lock.
        std::unique_lock<std::mutex> lockWorkers(mWorkersMutex);

        //  Add a worker.
        mWorkers.push(newWorker);

        //  Release the lock.
        lockWorkers.release();

        //  Notify all waiting threads.
        mWorkersCB.notify_all();
    }


    //  Begin executing any workers in the queue.
    inline virtual void begin()
    {
        //  
        mIsActive = true;

        //  Create all the Threads.
        for (unsigned int i = 0; i < mTaskerThreads.size(); i++)
        {
            mTaskerThreads[i] = std::thread(&Tasker::executeWorker, this);
        }
    }


    //  End the execution, waiting for all the workers in the queue to complete.
    inline virtual void end()
    {
        //  
        mIsEnd = true;

        //  Create a unique lock.
        std::unique_lock<std::mutex> lockWorkers(mWorkersMutex);

        //  Wait forever.
        while (true)
        {
            //  Lock the Workers.
            if (!lockWorkers.owns_lock())
            {
                lockWorkers.lock();
            }

            //  Check if all the work is finished.
            if (mWorkers.size() == 0)
            {
                //  Wait for all the threads to finish.
                for (unsigned int i = 0; i < mTaskerThreads.size(); i++)
                {
                    //  Wait for a thread to finish.
                    mTaskerThreads[i].join();
                }
            }

            //  Unlock the Workers Mutex.
            lockWorkers.release();
        }

        //  No longer active.
        mIsActive = false;

        //  No longer end.
        mIsEnd = false;
    }





private:

    //  Execute the Work on a Thread.
    inline virtual void executeWorker()
    {
        //  Create a unique lock.
        std::unique_lock<std::mutex> lockWorkers(mWorkersMutex);

        //  
        while (true)
        {
            //  Lock the Workers.
            if (!lockWorkers.owns_lock())
            {
                lockWorkers.lock();
            }

            //  Check if we have any work.
            if (mWorkers.size() > 0)
            {
                //  Get the first available work.
                std::shared_ptr<Worker> worker = mWorkers.front();

                //  Remove it from the queue.
                mWorkers.pop();

                //  Release the lock.
                lockWorkers.release();

                //  Execute the Work.
                if (worker != nullptr)
                {
                    worker->executeWork();
                }
            }
            else
            {
                //  
                if (mIsEnd)
                {
                    //  Release the lock.
                    lockWorkers.release();

                    //  Break.
                    break;
                }
                else
                {
                    //  Release the lock and wait.
                    mWorkersCB.wait(lockWorkers);
                }
            }
        }
    }


    //  The Vector of Tasker Threads.
    std::vector<std::thread> mTaskerThreads;

    //  The Mutex for the Vector of Workers.
    std::mutex mWorkersMutex;

    //  The Vector of Work Assignments.
    std::queue<std::shared_ptr<Worker>> mWorkers;

    //  Whether or not the Tasker is active.
    std::atomic_bool mIsActive = false;

    //  Whether or not the Tasker is ending.
    std::atomic_bool mIsEnd = false;

    //  Condition Variable the Workers wait on.
    std::condition_variable mWorkersCB;

};

工作人员:

代码语言:javascript
复制
#pragma once

class Worker
{

public:

    //  Default Worker Constructor.
    Worker() = default;

    //  Default Worker Destructor.
    virtual ~Worker() = default;

    //  Execute the Work. 
    virtual void executeWork() = 0;


private:


};
EN

回答 1

Code Review用户

回答已采纳

发布于 2017-09-11 17:55:15

逻辑错误: end()永远不会结束

end()需要以某种方式完成。

如果只在析构函数中调用end(),那么您就可以保证此时没有其他人与对象交互。这样就可以简单地说:

代码语言:javascript
复制
for (auto& thread : mTaskerThreads)
{
  //  Wait for a thread to finish.
  thread.join();
}

使用初始化程序列表

Tasker的构造函数应该如下所示:

代码语言:javascript
复制
Tasker(const unsigned int & newTaskerThreadCount)
  : mTaskerThreads(newTaskerThreadCount) {}

否则,您的向量将被设置为默认状态,然后被一个新的向量踩下。通过在列表中初始化它,它将直接进入最后的状态。

内联对于类声明

中定义的函数是隐式的。

代码语言:javascript
复制
inline virtual void addWorker(std::shared_ptr<Worker> newWorker) {...}
^^^^^^
redundant

使用基于范围的,除非您有理由不使用

它要干净得多,更重要的是,不容易出错。

代码语言:javascript
复制
for (unsigned int i = 0; i < mTaskerThreads.size(); i++)
//vs
for(auto& thread : mTaskerThreads) {...}

使用空()而不是将向量的大小与0

进行比较

代码语言:javascript
复制
if (mWorkers.size() == 0)
//vs
if (mWorkers.empty())

这么多虚拟函数

只有要重载的函数才应该是虚拟的。据我所知,Tasker中的任何函数都不是这样的。摆脱虚拟的。

通过值

传递小类型

在传递大型结构时,const type &有时可以提供很大的节省,但是对于核心类型,您实际上是在限制编译器。

代码语言:javascript
复制
Tasker(const unsigned int& newTaskerThreadCount);
//vs
Tasker(unsigned int newTaskerThreadCount);

显式begin()和end()创建了一个非常宽的不变量

我将摆脱begin()end()函数,只需在构造/销毁时实现它们,这将大大简化逻辑(完全摆脱mActive和mEnded,并使清理变得更简单)。告诉类的用户通过生命周期和作用域来管理这个周期是绝对好的。

Worker() =默认;是rundundant

如果您不添加任何其他构造函数,这就间接地为您完成了。

更喜欢头保护,而不是#实用化(

)

虽然#pragma once得到了广泛的支持,但它并不是该语言的一部分。如果您正在制作一个通用的、可移植的工具,您应该避免使用它。

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/175339

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档