C++中的线程池设计
我不知道如何把这个问题放在这个论坛中,我想问什么,并希望得到一些输入。C++中的线程池设计
我正在为我的项目编写一个线程池。我有以下设计。
我保持线程
std::vector<ThreadWrapper <threadFuncParam>* > m_vecThreads;
的载体和推动threds到列表
m_vecThreads.push_back(pThreadWrapper);
-
当新的请求到来时我正在线程池如下
if(!m_vecThreads.empty()) { ThreadWrapper <threadFuncParam>* pWrapper = m_vecThreads.back(); m_vecThreads.pop_back(); //... Awake threadd }
当线程工作完成后,它被推回到线程池。
趁现在gracefull关机我有设计优雅现在停止线程上面我面临的问题,我如何能阻止线程在vector容器我从矢量坡平当请求服务,所以我失去了指针直到服务完成。 有没有更好的我可以做到这一点或处理这种情况下,如地图或其他标准C++支持的容器?
另一个问题是
在关闭过程中,我有一个场景线程在这里做在我的情况下,来自这可能需要时间数据库中读取数据的过程,所以我不能等到它是完整的 ,我想送答复客户挂起的请求线程正在处理,我即将杀死该值是不好的。
谢谢!
为了解决你的第一个问题,把它推到另一个向量上,比如m_vecBusyThreads
,当它完成时,把它拿下来(注意,你必须有一些机制来搜索完成的线程)。对于你的第二个问题,最干净的解决方案是加入每个线程,直到它“关闭”,任何其他方法可能最终产生一些不良副作用(尤其是如果它连接到数据库等)。你有繁忙的容器,遍历告诉每个关闭,然后遍历每个免费的容器,关闭并加入每个线程。然后返回繁忙的容器并尝试加入每个线程。这可能会给繁忙线程一点时间关闭干净。
boost :: threads支持这种中断点的概念,其思想是你可以在任何这些点上中断一个线程,但是有些调用是不可中断的(通常是阻塞调用),你需要找到最好的方法以停止每种类型(例如套接字读取可能会发送一个虚拟数据包等)
我已经在C中完成了,所以解决方案不是“C++”ish,但我使用了两个数组:一个包含线程,另一个包含used/unused(〜布尔)的表示。
我会是这样的:
pthread_t[INITIAL_SIZE] thread_pool;
boolean[INITIAL_SIZE] threads_availability;
int first_available = 0;
pthread_t * get_thread() {
int ind = 0;
if (first_available<=INITIAL_SIZE) {
ind = first_available;
// find the next available spot
for (first_available; first_available < INITIAL_SIZE && threads_availability[first_available]; first_available++);
threads_availability[ind] = 0;
return thread_pool[ind];
}
}
void put_thread(pthread_t* thethread)
{
int i = 0;
pthread_t *it = thread_pool;
while (!pthread_equals(it, thethread)) {
it++;
i++;
}
thread_availability[i] = 1;
}
请记住,这是伪代码,这是不是最佳的。 但这是一个想法。
虽然在将一个使用过的物品放入另一个容器中存在一些开销,但对于较大的池,此解决方案可能会相当昂贵。 – stefaanv
如果您仍然需要访问您从池中传出的内容,则应将这些项目存储在“已用”容器中。
然而,在那一刻,你分享你的指针,所以你应该使用的shared_ptr,并传递出的weak_ptr,所以线程也可以删除,用户没有悬空指针
的最佳cointainer使用的项目将是一个集合,因此返回的线程可以很容易地找到并移除。
这不是您的问题的直接答案,因为其他人已经回答了您的原始问题。
我只是想说你可以看看boost :: asio和/或boost :: thread。 我可能会去boost :: asio,因为它拥有基于定时器和whatnot进行异步操作所需的一切。你可以使用shared_ptr和boost :: enable_shared_from_this来让你的“工作”完成并在他们完成工作时自动销毁。
例子:
boost::shared_ptr<async_job> aj(new async_job(
io_, boost::bind(&my_job::handle_completion, shared_from_this(), _1, _2)));
此代码将在一个线程池执行您的自定义async_job(io_是提高:: ASIO :: io_service对象)。当async_job完成并调用handle_completion时,您的'my_job'实例将自动销毁。或者,如果您在handle_completion中再次使用shared_from_this(),则可以让它生存。
HTH, 亚历
你有什么没有线程的载体而指针到线程的向量。你如何自己实例化线程,你用'new'手动执行吗?考虑将线程包装存储在另一个容器中,例如'std :: vector>',并将这些线程的地址放入'm_vecThreads'中。 –
leftaroundabout
你的“另一个问题”应该作为一个真正的其他问题被问及+你不清楚你的问题是什么。 – stefaanv