Threadpool design suggestions
In my application a number of tasks have to be executed parallely.
Since this number is very high we are maintaining a thread pool.The
basic idea is taken from CLR's thread pool documentations.
The major classes in this framework are
CSequencer : This class wraps a thread. In this a thread is created
and its wait for multiple objects m_hReadyToRunEvent and m_hStop. When
m_hReadyToRunEvent event is set the Sequencer executes the task
assigned to it.
Thread fn of sequencer is given below
DWORD WINAPI CCVSequencer::ExecuteThread( LPVOID lpParam )
{
CCVSequencer* pThis = (CCVSequencer*)lpParam;
while( 1 )
{
HANDLE hEvnts[] = { pThis->m_hReadyToRunEvent,
pThis->m_hStopEvent };
DWORD dwWaitFor = INFINITE;
if( pThis->m_bAutoDestroy )
dwWaitFor = 2 * 60 * 1000;
switch( WaitForMultipleObjects( 2, hEvnts, false,
dwWaitFor ) )
{
case WAIT_OBJECT_0 + 0:
{
pThis->Sequence();
m_pScheduler->AddSequencer( this );
break;
}
case WAIT_OBJECT_0 + 1:
{
return 0;
}
case WAIT_TIMEOUT:
{
m_bShuttingDown = true;
m_pScheduler->RemoveSequencer( this );
break;
}
}
}
return 0;
}
CScheduler: This class handles the thread request. For it maintains a
thread and two lists( m_lstFreeSequencers,m_lstTasks).
m_lstFreeSequencers contains the list of sequencers that
are waiting to get some task.
m_lstTaskList contains the tasks posted.
Whenever a tasks is posted to scheduler, it checks
m_lstFreeSequencers. If the m_lstFreeSequencers is empty,it creates a
new sequencer and add this to m_lstFreeSequencers.
Then it removes a sequencer from m_lstFreeSequencers, the task is
assigned to this retrieved sequencer and sets m_hReadyToRunEvent of
the sequencer. Once the operation is over sequencer informs the
scheduler to add it to m_lstFreeSequencers.
Problem: As you seen in the CCVSequencer::ExecuteThread() if a thread
get no task in 2 minutes it shutdowns automatically . For this it
informs the scheduler to remove it from m_lstFreeSequencer list. But
in some case between the time-out and m_bShuttingDown = true
statements scheduler assigns this thread for another task.
ie, a thread going to shutting down is assigned to a task.
How best can I avoid this problem?