I am currently developing a basic thread pool. I used c++11’s std::thread, along with std::condition_variable, and std::unique_lock. It seems to work, and I now would like to be able to kill some threads when too many of them are inactive.
For now, their jobs are given through a std::queue of boost::functions. I was thinking of adding a bunch of empty boost::functions so the threads know they have to exit their loop.
The thread’s loop is like this:
void ThreadPool::threadLoop()
{
boost::function<void ()> oThreadTask;
std::unique_lock<std::mutex> oLock(m_oTaskMutex);
while (1)
{
// m_oCV is a static std::condition_variable
// m_oTaskQueue is a static std::queue< boost::function<void ()> >
m_oCV.wait(oLock, [](){ return m_oTaskQueue.size(); });
oThreadTask = m_oTaskQueue.front();
m_oTaskQueue.pop();
m_oTaskMutex.unlock();
if (oThreadTask.empty())
break ;
oThreadTask();
}
// ??
}
The thing is, I’m not sure how to properly detach the thread once I exited the loop.
Would it be clean to look for the thread’s handle (I have access to a std::list<std::thread*>, and can compare their ids with std::this_thread::get_id()), and is it safe to call detach() from the thread itself, or even join()?
Yes, if you have all thread objects stored, you can find the one which
thread::idis equal tothis_thread::get_id(), and you can calldetach()on it, and destroy the thread object after that (the C++11 standard does not prevent that, and I believe it is based on the common practice). Make sure that no other execution thread accesses the instance ofstd::threadwhich is destroyed.But you cannot call
join()from the thread itself: an attempt for a thread to join with itself would result in a deadlock, and C++11 implementations should recognize that and throwsystem_errorwith the error condition ofresource_deadlock_would_occur.Alternatively, you can leave a message (e.g. via an std::atomic variable) to the main thread that the thread associated with a particular instance of
std::threadis about to complete its execution, and let the main thread join with this instance at a later point.