Computer Chess Club Archives


Search

Terms

Messages

Subject: Multithreading synchronization delima

Author: Russell Reagan

Date: 13:02:52 01/03/02


In my chess program I'm implementing the user input in it's own thread, as well
as implementing the ability for the main thread to create other worker threads
to do various tasks (the main one being searching a given position). I'll
explain my original idea, the problem I encountered with that idea, and my
solution and see if I missed anything and hopefully get some advice on how to
handle things correctly.

In each search thread class there is an event object used to determine if the
thread should shut itself down. So in the Shutdown() method of my thread class I
have something like this:

MyThreadClass::Shutdown()
{
    Lock(); // generic lock, implemented by critical section, mutex, whatever
    SetEvent(exitEventHandle);
    Unlock();
}

I'm doing this because the thread that is to be shut down will have to access
the exit event hadle, as well as the thread that requests the shutdown. This is
the first area I'm not entirely sure of. Do I need to lock handles to kernel
objects when passing them to functions like SetEvent, WaitForSingleObject,
WaitForMultipleObjects, etc.?

In the actual thread I have done something like this:

// ...
Lock();
if(WaitForSingleObject(thread->exitEventHandle, 0) != WAIT_TIMEOUT)
{
    // the exit event has been set, it's time to shut this thread down
}
Unlock();

This probably isn't the most efficient solution, but I don't forsee any problems
here as far as deadlock is concerned. Where I am concerned about deadlock is in
the main thread. In the main thread I have a call to WaitForMultipleObjects with
the timeout set at INFINITE. In my user input thread I have another event
object. I set this event object whenever the user has given input. This way,
anytime a thread returns, or a user gives input, the call to
WaitForMultipleObjects will return and I can handle the information returned
from the thread, or handle the user input. Here is where I'm concerned with
deadlock. In the user input thread I'll have something like:

// ...
Lock();
SetEvent(inputEventHandle);
Unlock();

And in my main thread I have:

Lock();
WaitForMultipleObjects(number, handles, false, INFINITE);
Unlock();
// handle whichever object was set

So when the main thread reaches the WaitForMultipleObjects call, it will own the
lock, and then it will wait for an event to be set. If no search threads are
running, then they won't cause any events to be set, and so the only remaining
source of an event being set would be from the user input, and the user input
thread will never be able to obtain the lock to set it's inputEventHandle
because the main thread owns the handle...deadlock.

My first idea for a solution to this is to implement the user input thread in
the same way as other threads, and wait on the input thread to return and handle
that object being set. I would simply restart the input thread each time input
was returned, and the call to WaitForMultipleObjects would return nicely.

In other words...

-User input thread gets input from user
-User input thread stores input in a global variable
-User input thread returns, setting it's kernel object and causing
WaitForMultipleObjects to return
-The main thread can safely access the data that was input from the input thread
since that thread is no longer running, it handles the input, and restarts the
input thread, and the process repeats

I'd like to know if I'm doing anything wrong in the initial example, and if my
second example of restarting the input thread everytime is a good solution or
not.

Russell



This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.