PDA

View Full Version : Win32 Multithreading



31337
04-25-2003, 06:14 AM
I'm sorry to take the topic directly off of OpenGL, but I have some questions on windows multithreading for a multiplayer game I'm making, and I figured you guys would be the ones with the answers.

I was working on a Win 2k computer with 2 processors on it and I was writing an app which ran 3 threads. The first thread, looped infinately displaying a message with printf(). The second thread, did the same thing with another message. The third thread's job was to manage the other two threads with the SuspendThread() and ResumeThread() commands because when two printf()'s run at the same time, it crashes the computer.

However, *nomatter* WHAT I did, I could not get it to go forever without crashing. Originally my 3rd thread's code looked like this:

for(; http://www.opengl.org/discussion_boards/ubb/wink.gif {
ResumeThread(thread1);
SuspendThread(thread1);
ResumeThread(thread2);
SuspendThread(thread2);
}

Believe it or not, but that approach actually made it work best. When I made it more complicated, like including boolean's as flags for completion and what not, it crashed even earlier. Something is up. There has to be a trick to this. It would run for about 5 minutes and then crash.

Personally my theory is that since there are 3 threads and 2 processors, sometimes the two processors would end up on the same thread. The third thread that is. One would be in the middle of suspending one thread, and the other would jump in front of it. When it jumped in front, it would resume the other thread before the other could be suspended. Then two printf()'s would occur at the same time, creating a crash.

I know in UNIX there are locks. There *has* to be a similar approach on Windows. I'm beginning to think that multithread'd apps on multiprocessor machines with windows == bad.

Thanks for any help, knowledge, or reference you can give me.

Rog
04-25-2003, 06:49 AM
Look in the help (e.g. MSDN) - specifically, look at "critical section" and "mutex". Everything you need is there .....

jwatte
04-25-2003, 09:34 AM
SuspendThread() and ResumeThread() are not "safe" calls, because they may (literally) suspend the threads ANYWHERE. If a thread gets pre-empted while holding, say, a malloc() heap lock, and you then SuspendThread() it, then nobody else can malloc() until you ResumeThread() the thread and it gest to releasing the thread.

KillThread() is dangerous for the same reason. You really want to only suspend/resume/terminate at well-defined times, when you know resource allocations are balanced and there are no ordering hazards. That's why the OS provides things like mutexes (pthreads), critical sections (Windows), events (Windows) and semaphores (SysV).

If you use the multithreaded DLL version of the runtime libraries on Windows, you shouldn't crash even if two threads printf() at the same time, btw.

jwatte
04-25-2003, 09:43 AM
Oh, and this is not the right board to post this question to.

31337
04-25-2003, 09:45 AM
What board should I post this to http://www.opengl.org/discussion_boards/ubb/smile.gif

Martin_unique
04-25-2003, 09:46 AM
Hello,
If you are new to multithreaded programming this might be a good starting point: http://www.serpentine.com/~bos/threads-faq/
This is the faq for comp.programming.threads - you might also browse the newsgroup.
In general, if a piece of code is run in two or more threads at the same time, and you do not provide any synchronization mechanisms (assuming the code is modifying some data), you will get into trouble. However, printf should not crash your program, when run from separate threads. I would also look into other parts of your code, this sounds more like a memory issue. Still, synchronization is necessary when dealing with threads.
I hope this helps,

Martin

31337
04-25-2003, 09:59 AM
And can I get some more specifics? I can't find anything on MSDN. What are the function names for creating "mutex"s? Thanks

31337
04-25-2003, 10:29 AM
Nevermind I got it thanks for your help. The trick is EnterCriticalSection() http://www.opengl.org/discussion_boards/ubb/smile.gif

Rog
04-25-2003, 10:48 AM
Originally posted by 31337:
The trick is EnterCriticalSection() http://www.opengl.org/discussion_boards/ubb/smile.gif

Yep, that's better than the way you were handling it. There's much much more to it than just critical sections though - especially if you are synchronising threads in different processes. A good place to start in MSDN is -
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/synchronization.asp

Great for insomnia too .....

marcus256
04-25-2003, 11:40 AM
You may want to look at the GLFW Users Guide ( PDF (http://glfw.sourceforge.net/files/glfwug14.pdf) ). It has a section on the two most basic thread operations (chapter 8): data protection (mutexes) and thread synchronization (note that GLFW uses a different - and more elegant IMO - method for synchronization than Win32 does).

Regarding printf, I think you will be allright if you link with the multi threaded version of the MSVC runtime (check the MSVC/MSDN help/doc).

31337
04-25-2003, 02:55 PM
Thanks for your help guys you rock. However, forget about printf(), it was just a simple test.

However now I have questions regarding the winsock API and being multithreaded. My server app setup looks like this:

1 thread for recieving commands at the command prompt and executing them.
1 thread for each client which recieves packets from them, all of which execute the recv() command simultaniously (I dont see any reasonable way around this, will it work out ok?)
and 1 thread for sending out updated packets to each user. Since every user gets the same packet data, I figure that I only need 1 thread.

Will this work out ok? Whats the best way to go about it?

Should I use UDP for my game or TCP?

The last UDP app I wrote worked... kindof. I was sending the length of a message then a message, and when it was recieving the packet it was getting absurd sizes for the message, everything from signed values (causing negative memory allocation = crash) and allocation for a 10 megabyte message (not happening). Anybody have any ideas for why this was happening?

Thanks, and once again, sorry to go off topic but I figure its for a GL project so its somewhat relevant...