Re: Threadpool design suggestions
On Mar 23, 7:59 pm, Joseph M. Newcomer <newco...@flounder.com> wrote:
See below...
On Mon, 23 Mar 2009 04:44:39 -0700 (PDT), Faisal <faisal...@gmail.com> wr=
ote:
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_hReadyToR=
unEvent,
pThis->m_hS=
topEvent };
****
The order is important here. This says that the processing is more imp=
ortant than the
stopping. However, this has implications in how you shut down your app=
, because if the
queues have a lot to do, you won't be able to stop until everything is do=
ne. Of course,
that's a reasonable design if you understand that you will always have to=
defer shutting
down until everything is processed, but it also means that you can't shut=
down
immediately.
****
DWORD dwWaitFor = INFINITE;
if( pThis->m_bAutoDestroy )
dwWaitFor = 2 * 60 * 1=
000;
****
An interesting idea.
****
switch( WaitForMultipleObjects( 2, hEvnt=
s, false,
dwWaitFor ) )
{
case WAIT_OBJECT_0 + 0:
{
pThis->S=
equence();
uler->AddSequencer( this );
break;
}
case WAIT_OBJECT_0 + 1:
{
return 0=
;
}
case WAIT_TIMEOUT:
{
m_bShutt=
ingDown = true;
uler->RemoveSequencer( this );
break;
****
But was it really your intention that if you time out, that you leave thi=
s thread running?
****> }
}
}
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.
****
Actually, this seems all unnecessarily complicated. I'd simply create =
an I/O Completion
Port, have all the threads wait on GetQueuedCompletionStatus(..., INFINIT=
E), and eliminate
entirely the concept of a scheduler/dispatcher because it is already buil=
t in. To enqueue
a request, PostQueuedCompletionStatus, with a key that says "I have work =
to do". To shut
down the thread, PostQueuedCompletionStatus with a key that says "shut do=
wn". End of
problem. You have created a large, complex mechanism to solve a proble=
m that takes zero
lines of code.
****
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?
****
Mostly, by getting rid of the whole concept of the sequencer and the time=
out. You don't
need them. Use an IOCP, and the whole sequencing mechanism is free. =
No need for
timeouts, no need for a scheduler, no need to deal with sequencing things=
, *it is all
built into the IOCP*.
=
joe
****
Joseph M. Newcomer [MVP]
email: newco...@flounder.com
Web:http://www.flounder.com
MVP Tips:http://www.flounder.com/mvp_tips.htm
Joe, Thanks for your suggestions.
I am not much familiar with IOCompletionPort APIs. When I checked the
documentation it seems that IOCP is a way to synchronize the
asynchronous IO operations. And it is always associated with some IO
handle.
In my case, there is no IO operation is involved. I want to do a
number of things in parallel. Some times these threads have to be
joined, some times one thread have to be split in to different
sequence paths.
Could you please suggest a pattern which would make send to my
problem?