This is copied from my answer to another very similar post:
Start with maximum number of threads the system can support:
int num_threads = std::thread::hardware_concurrency();
For an efficient threadpool implementation, once threads are created according to num_threads
, it's better not to create new ones, or destroy old ones (by joining). There will be a performance penalty, an it might even make your application go slower than the serial version.
Each C++11 thread should be running in their function with an infinite loop, constantly waiting for new tasks to grab and run.
Here is how to attach such a function to the thread pool:
int num_threads = std::thread::hardware_concurrency();
std::vector<std::thread> threads;
for (int i = 0; i < num_threads; i++)
{
pool.push_back(std::thread(Infinite_loop_function));
}
- The infinite loop function. This is a
while (true)
loop waiting for the task queue.
void Pool::Infinite_loop_function()
{
while (true)
{
{
std::unique_lock<std::mutex> lock(queue_mutex);
condition.wait(lock, [this](){
return !queue.empty() || terminate_pool;
});
Job = queue.front();
queue.pop();
}
Job(); // function<void()> type
}
};
- Make a function to add job to your queue
void Pool::Add_Job(function<void()> New_Job)
{
{
std::unique_lock<std::mutex> lock(queue_mutex);
queue.push(New_Job);
}
condition.notify_one();
}
- Bind an arbitrary function to your queue
Pool_Obj.Add_Job(std::bind(&Some_Class::Some_Method, &Some_object));
Once you integrate these ingredients, you have your own dynamic threading pool. These threads always run, waiting for job to do.
I apologize if there are some syntax errors, I typed this code and and I have a bad memory. Sorry that I cannot provide you the complete thread pool code; that would violate my job integrity.
Edit: to terminate the pool, call the shutdown()
method:
Pool::shutdown()
{
{
std::unique_lock<std::mutex> lock(threadpool_mutex);
terminate_pool = true; // use this flag in condition.wait
}
condition.notify_all(); // wake up all threads.
// Join all threads.
for (std::thread &th : threads)
{
th.join();
}
pool.clear();
stopped = true; // use this flag in destructor, if not set, call shutdown()
}
Note: the anonymous code blocks are used so that when they are exited, the std::unique_lock
variables created within them go out of scope, unlocking the mutex.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…