Skip to main content
gamedev.net
🔒 Locked

Simple thread communication question

Started by Russell Apr 11, 2002 at 2:24 PM 4 replies 250+ views
Original Post
Russell
Russell
I''m writing my program (chess program) with two main threads. An input thread and a search thread. I plan on having several interfaces to my program (console, GUI, Internet Chess Server, etc.) so I chose to implement my "commands" according to the "commands" that are used to communicate on Internet Chess Servers so my program can play against other programs online. The protocol calls for various commands to be handled immediately in some cases, and if my program is halfway into a search that isn''t going to be done for another minute, it can''t very well handle the commands right away. Anyway, I basically only need a single global flag to tell my search thread to wrap up what it''s doing and bail out. For example, if the user sends a "new game" command and the program is in the middle of a search, the search is no longer needed and can simply stop. Or if the user entered the "move now!" command, the search thread needs to report back with the best move it found so far and make that move, and stop searching. So I really only need one little flag to communicate between the threads, and I''m attempting to make my program as portable as I can (it''s not so easy with multithreading) so using WIN32 specific solutions (Interlocked* functions) is out. I''m using pthreads in my attempt to remain as portable as possible. My other idea was to just use a single volatile int to communicate between the two threads. Will this solution work or not? I suppose that if in my search I checked the flag several times a second, it wouldn''t matter if my search thread missed it the first time by due to some unforseen complication with the other thread changing the variable (I have no idea if this would ever happen). I could just catch the flag in another 100 ms or whatever. If that solution will not work, do I have any other solution besides using a more expensive synchronization method such as mutexes, etc.? Any help is appreciated. Russell
Oluseyi
Oluseyi
Don''t do that. It''s messy and requires signalling. Use thread procedure messages instead. Create a message queue in your search procedure and then send a SM_QUIT message or whatever to your search thread. Once the search thread receives this it should clean up and shut down.

Of course this means your search thread needs to check its message queue regularly... Alternatively you could use a TerminateThread-like call to end the thread whenever, so the thread itself is oblivious to external processing. The problem with this method is that it doesn''t clean up, which can result in significant memory leaks.

[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! | Asking Smart Questions ]
Thanks to Kylotan for the idea!
Russell
Russell
It seems like this method just means you have to create some sort of locking mechanism anyway to ensure that the data in the queue isn''t being written to in the input thread while trying to be read from in the search thread. Aside from that, I still need a method for telling the search thread that there is a message available. If I could accomplish the task of getting a message to my search thread without using any kind of locking mechanism, then I could just as easily set a "stop search" flag or something and test that in my search thread instead of testing the "is there a message to process" flag.

Perhaps I''m missing something, but this seems to bring us right back to square one.

Russell
Stoffel
Stoffel
Yes, you need a synchronization object. Any thread library should have them. For win32, Mutex is one commonly used synch object. Find something similar for pthreads. They might call them semaphores (of which a Mutex is a special type).
Oluseyi
Oluseyi
Here''s a Win32 example

DWORD WINAPI SearchThreadProc( void * pArg )
{
std::queue< SEARCH_STRUCT > SearchQueue;
MSG msg;
PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ); // create message queue
//
while( true )
{
// check for message
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
// process message
switch( msg.message )
{
case SM_QUIT:
{
SearchQueue.clear();
return 0;
}
case SM_ADDSEARCH:
{
// add new search to queue
SearchQueue.push( msg.wparam ); // or whatever parameter
}
break;
// other messages...
}
}
else
{
if( SearchQueue.empty() )
// queue will not be filled until we receive
// another "SEARCH" message from the input thread
WaitMessage();
else
{
// do alternate processing - search in your case
}
}
}
return 0;
}


[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! | Asking Smart Questions ]
Thanks to Kylotan for the idea!
CheeseGrater
CheeseGrater


Well, you could always open a pipe between threads. That''s a more portable way to do what Oluseyi suggests with message queues, but I''ve never really been a fan of that method of inter process communication.

Anyway, as long as your variable update is purely one way and atomic on all platforms, Your method with the shared variable will work. Only thread A writes to variable x, and it only writes to _one_ variable x to communicate.

So you can get away with having thread A update a variable that thread B reads. The problem happens when B needs to read 2 variables, or when B changes the variable to communicate back with A. If you''re confident you''re not going to forget about these issues in 6 months when you''re maintaining this code, go ahead.

But using a mutex or a semaphore now will probably save you a lot of headaches later, and they have been implemented on just about every platform I''ve ever seen, so they''re pretty portable.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.