如何使线程池任务成为抽象函数类型?

问题描述 投票:0回答:1

我正在尝试实现非常简单的C ++线程池。到目前为止,我已经检查了它的工作情况。但是,我想以抽象形式进行任务。我搜索了数十篇文章,它们似乎不是我想要的。(也许我的关键字不合适...)当前,仅

void (*)()

表格可以接受为任务功能。下面编写了简单的代码。

#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <Windows.h>

class CYSThreadPool
{
private:

    static std::thread** s_ppThreads;
    static long s_lThreadCount;
    static bool s_bJoin;
    static std::mutex* s_pMutexJoin;

    static std::queue<void (*)()> s_queueTasks;
    static std::mutex* s_pMutexTasks;

    CYSThreadPool(){}
    ~CYSThreadPool(){}

    static void ThreadFunction()
    {
        while (true)
        {
            if (!s_pMutexJoin->try_lock())
                continue;

            bool bJoin = s_bJoin;
            s_pMutexJoin->unlock();

            if (bJoin)
                break;

            if (!s_pMutexTasks->try_lock())
                continue;

            void (*fp)() = nullptr;
            if (s_queueTasks.size() > 0ull)
            {
                fp = s_queueTasks.front();
                s_queueTasks.pop();
            }

            s_pMutexTasks->unlock();

            if (fp != nullptr)
                fp();
        }
    }

public:

    enum class EResult : unsigned long
    {
        Success = 0ul,
        Fail_Undefined = 1ul,
        Fail_InvalidThreadCount = 2ul,
        Fail_ArgumentNull = 3ul
    };

    static const EResult Join()
    {
        if (s_ppThreads == nullptr)
        {
            if (s_lThreadCount == 0l)
                return EResult::Success;
            else
                return EResult::Fail_Undefined;
        }
        else
        {
            if (s_lThreadCount <= 0l)
                return EResult::Fail_Undefined;
            else
            {
                s_pMutexJoin->lock();
                s_bJoin = true;
                s_pMutexJoin->unlock();

                for (long i = 0l; i < s_lThreadCount; ++i)
                {
                    s_ppThreads[i]->join();
                    s_ppThreads[i] = nullptr;
                }

                delete s_ppThreads;
                s_ppThreads = nullptr;
                s_lThreadCount = 0l;

                s_pMutexJoin->lock();
                s_bJoin = false;
                s_pMutexJoin->unlock();
            }
        }

        return EResult::Success;
    }

    static const EResult CreateThreads(const long _lThreadCount)
    {
        if (_lThreadCount < 0l)
            return EResult::Fail_InvalidThreadCount;

        if (Join() != EResult::Success)
            return EResult::Fail_Undefined;

        if (_lThreadCount == 0l)
            return EResult::Success;

        s_ppThreads = new std::thread*[_lThreadCount]{};

        for (long i = 0l; i < _lThreadCount; ++i)
            s_ppThreads[i] = new std::thread(ThreadFunction);

        s_lThreadCount = _lThreadCount;

        return EResult::Success;
    }

    static const EResult AddTask(void (*_fp)())
    {
        if (_fp == nullptr)
            return EResult::Fail_ArgumentNull;

        s_pMutexTasks->lock();
        s_queueTasks.push(_fp);
        s_pMutexTasks->unlock();

        return EResult::Success;
    }
};

std::thread** CYSThreadPool::s_ppThreads = nullptr;
long CYSThreadPool::s_lThreadCount = 0l;
bool CYSThreadPool::s_bJoin = false;
std::mutex* CYSThreadPool::s_pMutexJoin = new std::mutex();
std::queue<void (*)()> CYSThreadPool::s_queueTasks;
std::mutex* CYSThreadPool::s_pMutexTasks = new std::mutex();

void Test0()
{
    for (long i = 0l; i < 100000l; ++i)
    {
        std::cout << "A";
    }
}

int main()
{
    CYSThreadPool::EResult eResult = CYSThreadPool::Join();
    eResult = CYSThreadPool::CreateThreads(-1l);
    eResult = CYSThreadPool::CreateThreads(1l);
    eResult = CYSThreadPool::CreateThreads(0l);
    eResult = CYSThreadPool::CreateThreads(2l);

    CYSThreadPool::AddTask(Test0);

    Sleep(1000ul);

    CYSThreadPool::Join();

    return 0;
}

详细的答案将不胜感激!

编辑:

我所说的“抽象形式的函数”的意思是获取除void()()之外的任何函数类型。例如void()(long),void(](ID3D12Resource1,IDXGISwapChain)或HResult()(ID3D12Device6,ID3D12Resource1 *,IDXGISwapChain)等。

感谢有关使用condition_variable而不是try_lock并将fp()包装到try-catch中的注释。抱歉,我不明白我的意思。我可以要求更多信息吗?

c++ task threadpool abstraction
1个回答
2
投票

因此,有几件事可以改善您的代码:

  1. 您可以使用std::function<void()>代替void(*)()。这将允许您通过将它们包装在lambda中来调用任何可调用的,不仅是函数指针,例如CYSThreadPool::AddTask([]() { Add(3, 1); });
  2. 甚至更好,使用虚拟Task方法创建一个抽象基类,例如说.Run()并使用它。如果需要,可以从中派生出FunctionPointerTaskStdFunctionTask(显然可以更改名称)。您可以创建说ProcessResource1Task并将必要的参数传递给构造函数,以便.Run()仅执行它。
  3. 您的ThreadFunction工作人员效率很低。您一直在try_lock上旋转。别。请改用condition_variables
  4. 甚至更好,将排队的内容移到单独的线程安全队列类中。
  5. 您的代码不是异常安全的。不要使用手动锁/ try_lock,而要使用lock_guardunique_lock。由于它是您的代码,因此很容易死锁。如果必须使用手动锁/ try_lock,则必须使用try-catch。
  6. 很多静态变量。别。使它们全部都是非静态成员,添加适当的构造函数和析构函数。一旦加入,您的线程池将完全无法使用。再加上Join()也不是线程安全的(如果线程池不是完全静态的,那将变得无关紧要)。
  7. 您可以通过设置bool s_bJoin atomic来提高性能。无需在锁下读取/写入它。

可能还有其他问题,这是我现在可以看到的。

您还可以查看this code以获取不错的线程池实现。它很短,并且利用了上面的大多数提示。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.