我正在尝试实现非常简单的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中的注释。抱歉,我不明白我的意思。我可以要求更多信息吗?
因此,有几件事可以改善您的代码:
void(*)()
。这将允许您通过将它们包装在lambda中来调用任何可调用的,不仅是函数指针,例如CYSThreadPool::AddTask([]() { Add(3, 1); });
。Task
方法创建一个抽象基类,例如说.Run()
并使用它。如果需要,可以从中派生出FunctionPointerTask
或StdFunctionTask
(显然可以更改名称)。您可以创建说ProcessResource1Task
并将必要的参数传递给构造函数,以便.Run()
仅执行它。ThreadFunction
工作人员效率很低。您一直在try_lock
上旋转。别。请改用condition_variables。bool s_bJoin
atomic来提高性能。无需在锁下读取/写入它。可能还有其他问题,这是我现在可以看到的。
您还可以查看this code以获取不错的线程池实现。它很短,并且利用了上面的大多数提示。