To ensure that users wishing to dispatch a work item to the thread pool can do so without blocking we implement the user level dispatch function as follows:
void CThreadPool::Dispatch(
ULONG_PTR completionKey,
DWORD dwNumBytes /*= 0*/,
OVERLAPPED *pOverlapped /*= 0*/)
{
if (completionKey == 0)
{
throw CException(_T("CThreadPool::Dispatch()"), _T("0 is an invalid value for completionKey"));
}
m_dispatchPort.PostStatus(completionKey, dwNumBytes, pOverlapped);
}
The restriction on 0 valued completion keys is unfortunate but allows us to shut down the thread pool's dispatch thread by posting a 0 to its completion port. The thread pool now has two IO Completion Ports. The dispatch port is serviced by a single maintenance thread which executes the HandleDispatch() method to dispatch work items to the worker threads. Users dispatch without blocking and the maintenance thread dispatches in a blocking manner so that it can expand the thread pool when it needs to. The work item port is serviced by a variable number of threads. We've seen how we know when we need to expand the number of threads, now we'll look at how we reduce the number of threads when the work load is low.
Comments