让线程池的所有线程执行给定的函数
Have all threads of a thread pool execute a given function
我使用了一个稍微定制的 progschj 线程池实现版本 (https://github.com/progschj/ThreadPool)。到目前为止,它在我的用例中运行良好,但下文描述的除外。
我希望能够让池中的每个线程执行一次给定的函数,例如为了让每个线程设置一些线程局部变量。
thread_pool.execute_all([] () { do some stuff; });
这个调用应该是阻塞的,等待直到池中的所有线程都执行完该函数。
我曾尝试修改线程的主循环来实现此目的,但我无法设法确保池中的每个线程都恰好执行给定函数一次并且主线程等待它们完成。
任何人都可以提出此功能的工作版本,或给出有关如何实现此功能的提示吗?
写一个计数信号量屏障。
struct counting_barrier {
explicit counting_barrier( std::ptrdiff_t c ):count(c) {}
void operator--(int)& {
this->operator--();
}
void operator--()& {
auto l = lock();
--count;
cv.wait( l, [&]{
return count<=0;
} );
cv.notify_all();
}
private:
std::unique_lock<std::mutex> lock()& {
return std::unique_lock<std::mutex>(m);
}
std::condition_variable cv;
std::mutex m;
std::ptrdiff_t count = 0;
};
现在我们可以使用现有的原语来实现它。
template<class F>
void execute_all( F&& f ) {
counting_barrier barrier(workers.size()+1);
for (std::size_t i = 0; i < workers.size(); ++i) {
enqueue([&]{
f();
--barrier;
});
}
--barrier;
}
应该就可以了。在 workers.size()
撞到障碍之前,任何工人都不得越过障碍;当最后一个工人释放屏障时,workers.size()-1
必须 被阻塞。因此每个工人在函数 returns.
之前调用 f()
代码未经测试。
我使用了一个稍微定制的 progschj 线程池实现版本 (https://github.com/progschj/ThreadPool)。到目前为止,它在我的用例中运行良好,但下文描述的除外。
我希望能够让池中的每个线程执行一次给定的函数,例如为了让每个线程设置一些线程局部变量。
thread_pool.execute_all([] () { do some stuff; });
这个调用应该是阻塞的,等待直到池中的所有线程都执行完该函数。
我曾尝试修改线程的主循环来实现此目的,但我无法设法确保池中的每个线程都恰好执行给定函数一次并且主线程等待它们完成。
任何人都可以提出此功能的工作版本,或给出有关如何实现此功能的提示吗?
写一个计数信号量屏障。
struct counting_barrier {
explicit counting_barrier( std::ptrdiff_t c ):count(c) {}
void operator--(int)& {
this->operator--();
}
void operator--()& {
auto l = lock();
--count;
cv.wait( l, [&]{
return count<=0;
} );
cv.notify_all();
}
private:
std::unique_lock<std::mutex> lock()& {
return std::unique_lock<std::mutex>(m);
}
std::condition_variable cv;
std::mutex m;
std::ptrdiff_t count = 0;
};
现在我们可以使用现有的原语来实现它。
template<class F>
void execute_all( F&& f ) {
counting_barrier barrier(workers.size()+1);
for (std::size_t i = 0; i < workers.size(); ++i) {
enqueue([&]{
f();
--barrier;
});
}
--barrier;
}
应该就可以了。在 workers.size()
撞到障碍之前,任何工人都不得越过障碍;当最后一个工人释放屏障时,workers.size()-1
必须 被阻塞。因此每个工人在函数 returns.
f()
代码未经测试。