Archived

This topic is now archived and is closed to further replies.

ProgramMax

Thread syncro

Recommended Posts

Could someone provide me with a decent example of a Critical Section in use and a Mutex object in use? When is it appropriate to use one and not the other? Thanks!

Share this post


Link to post
Share on other sites
On Windows, a critical section is valid within a process and a mutex is valid across processes.

For details:

http://www.microsoft.com/msj/0198/Win320198.htm
http://spiderman.dyn.ee/papers/multithreading.html
http://www.devguy.com/fp/Tips/synchronization.htm
http://www.codeproject.com/threads/opbmutex.asp

google: win32 critical section mutex synchronization

Share this post


Link to post
Share on other sites
Thanks. Actually just while waiting on the responce I found some good info and then did some thinking. I read earlier that critical sections are not shared across multiple processes. After my initial post, I read that critical sections are also faster than mutex objects.

So then I sat down and did some thinking. I have one thread that loads a queue with triangles and needs to tell the rendering thread when it is okay to start adding the triangles to the VB and IB. I also needed a good way to test when the rendering thread should shut down. Currently I have the code closing the thread right in the middle of the run. This could mean that in the middle of a DirectX call, the thread terminates. I don''t like the idea of that.

Anyway, here is my thinking (in terms of the termination critical section). I want to minimize the calls to Enter/LeaveCriticalSection() per frame. Instead of calling Enter and Leave every frame, and ending the loop when I couldn''t Enter, I wanted to find a better answer.

I came up with kinda a reverse-ownership critical section. If my rendering thread never gets ownership, it will never have to call LeaveCriticalSection(). So what I plan to do is have another thread own the critical section and have the rendering thread while( ! TryEnterCriticalSection() ). That way each frame never actually gets ownership. When I want the thread to end, it will gain ownership and will then Leave and close the thread.

Anyway, thanks for the links

Share this post


Link to post
Share on other sites
Associate the CS with data, not with a thread. The point of a CS is to ensure that data access is restricted to one thread at a time.

I''m leary of wrapping TryEnterCriticalSection in a while statement like that. The advantage of TryEnterCriticalSection is that it never suspends a thread - putting it into a while loop like that appears to remove that advantage.

Share this post


Link to post
Share on other sites
I understand that a CS is designed for sharing data between threads. However I needed some way to signal the end of the program so the other thread can close properly. Using a variable would get rid of the whole benefit of a CS, so I use a CS to mark the end of a thread.

As for the TryEnterCriticalSection(), I know that it is designed to avoid the block. Infact that''s exactly what I''m using it for. You see, now that I explained I need the CS to check for the end of the execution, I also now need a way to use that CS. The last thing I want is to add a block to my rendering thread. If I had a block in my rendering thread (other than rendering) I would kill myself. So anyway, my goal was to reduce the penalty of using a CS as much as possible. I figured I would use TryEnterCriticalSection() to avoid the block, but didn''t want to enter the critical section and then leave the critical section every frame. That would add even more overhead to each frame. So I figured if I could have a while loop that goes so long as TryEnterCriticalSection() fails, I wouldn''t have to enter/leave, and I would still have a signal to tell me wether or not I need to exit the thread.

So in a way, I took all the benefits of a CS and multithreading, but reversed the idea around a little bit so it would run faster.

The only real change I made was to inverse things. Instead of trying to have ownership of the CS, my rendering thread trys to NOT have ownership. As soon as it gains ownership, it knows it is time to close down the thread. That means my rendering thread now enters and leaves the CS only once, instead of once per frame. That is some hard-core improvement if you ask me.

Share this post


Link to post
Share on other sites
quote:


... so I use a CS to mark the end of a thread....
... Instead of trying to have ownership of the CS, my rendering thread trys to NOT have ownership. As soon as it gains ownership, it knows it is time to close down the thread.




Hi there,

I know quite well what you are trying to archive since I also
went the same way. There is a much cleaner way, actually the way
it was designed to be

The handle returned by CreateThread, _beginthread, ... whatever
is actually an ''event''. So when you wait for your thread to exit,
just make a call to

WaitForSingleObject(hThread2Die,INFINITE);

in the Thread that has to wait. That''s it. Only after that
a call to CloseHandle will be safe. Your original method isn''t
safe, only an assumption that the thread might have ended. Killing it with ExitThread is another story.

Hope this is some help to you.

Lorenz

Share this post


Link to post
Share on other sites
I know....I have that too. Here is a scenario:

say I have a thread, and the function the thread calls looks like this:

while( true )
{
// loop stuff
}

Given that scenario, the WaitForObject(blah, INFINITE) will never come...the loop always continues.

To remedy this I had to change that true to something else...I needed a way to find when the thread needed to exit. So I changed the loop to this:

while( ! TryEnterCriticalSection( blah ) )
{
// loop stuff
}
LeaveCriticalSection( blah );
return 0;

The main thread still calls WaitForSingleObject() and all to make it nice and clean...just it tells the thread that it is ready to shut down before it does that.

Give me a while and I will write a better description of the problem and my solution. I think it is pretty clever actually.

Share this post


Link to post
Share on other sites
Okay, it''s write-up time. The first step in designing my code went into figuring out where each block is. A block is when the code stops execution and waits for something to happen. An example is GetMessage().

After I found my blocks, I started designing a way to keep each block in its own thread, and then have one extra worker thread. Anything more would be kinda wasteful.

An important note is to not try to avoid blocks. If I use PeekMessage() instead of GetMessage(), my program will take 99% of the CPU and will operate the same as it did anyway. Use blocks where you can.

After finding that I would have one block for the message pump and another block for rendering, I decided to put the rendering in a seperate thread. A thread will start up and run the thread''s function once. That means as soon as the function returns, the thread is ready to be closed. Obviously we want our rendering function to be called more than once. Infact it should loop until the engine is done.

So I put a while(true){...} in the thread. Now the rendering thread can be closed at any time, but that wouldn''t make for a clean and safe close. Especially because the thread is working with DX. Infact every now and then I was getting access violations when trying to close the thread. To combat that, I needed a way to exit the loop when it is time to close down the thread. I am looking for a way to while(active){...}, but I need to make it thread-safe and use as little CPU as possible. Remember, this is going to be called once each frame.

To fix the thread-safe issue, I created a critical section. I use the critical section as a boolean, true of false, wether the rendering thread had ownership or not. If the rendering thread could get ownership, it would continue rendering and then leave the critical section at the end of the rendering. This changed my loop to look like this: while( TryEnterCriticalSection(blah)){...LeaveCriticalSection(blah) }

I noticed that this meant I was now calling Leave each frame, plus am also Entering the Critical Section on each frame. I wanted to keep overhead as low as possible, and adding two system function calls isn''t going to help that. Then I realized that TryEnter will exit prematurely if it fails, if you can''t enter.

So long as another thread has ownership, TryEnter will fail and you won''t have to Leave. Plus you know the TryEnter exited prematurely and didn''t execute all of the function''s code, saving even a little bit of execution time in just that function. I decided to change my scheme then to that of a reverse Critical Section. Either way I just needed a bool to tell me if I should terminate.

While I want the rendering thread to run, I have the main thread keep ownership of the Critical Section. As soon as it is time to terminate the thread, the main thread gives up ownership. The rendering function now looks like this:
while( ! TryEnterCriticalSection( blah ) )
{
...
}
LeaveCriticalSection( blah )

That way the loop continues as needed, and you only actually enter and leave the CS once (when the thread exits).

The Reverse Critical Section aims at NOT having ownership, as opposed to the Critical Section that wants ownership.

Quick side notes: 1.) How do you put parts of a message into those code blocks? And, 2.) If this hasn''t been coined yet, I hereby claim the Reverse Critical Section as my own.

Share this post


Link to post
Share on other sites
Just a question.

Why do you want to use that CS Stuff for your rendering loop ?
Why not just a simple bool like ''bStopRendering'' ?

If you want to stop the thread then just set it ''true''.
You can be sure that nothing will be faster than that.
After that cleaning up will be easy.

An example would be

void Thread
{
while(!bStopRendering)
{
// Render
}

DX_CLeanUP();
}

The calling thread will set that bool and make a call to
WaitForSingleObject right after and return when the threads allocated memory is released.

quote:

How do you put parts of a message into those code blocks?



What do you mean by ''parts'' ?

Share this post


Link to post
Share on other sites
The other thread would need to set the bool''s value. For example:
Main thread: bRendering = false;
Render thread: while( bRendering )

But then you run into thread problems. I think you get an access violation or something funky when both threads try to access the same variable at the same time. Being that the rendering thread is always accessing the variable, the chances are high that they would access at the same time.

I''m not sure if this is the actual error or what not, but I do know that before I put the CS into my code, I was getting access violations when closing the thread prematurely. Now the code still works at the same FPS it did and has no violation errors.

What I meant by code blocks is that I had seen areas where someone had an html form or something funky to encapsulate their code. When posting to the forums, they would put their code in a html frame and it would make the whole post easier to read and a little cleaner. I wondered if that was just pure html or some special BB code or something funky.

Thanks.

Share this post


Link to post
Share on other sites
quote:
Original post by ProgramMax Being that the rendering thread is always accessing the variable, the chances are high that they would access at the same time.


The OS and the CPU are designed so that preemption is done only when an instruction is completed on a single-CPU machine. On a DEC Alpha, MIPS and multi-CPU machines, that could be a problem so the InterlockedIncrement() et al. API was devised.

quote:
Original post by ProgramMax I want to minimize the calls to Enter/LeaveCriticalSection() per frame.


Have you tried to profile the calls, i.e. try to determine how much time an Enter/Leave pair is going to take you wrt the rendering code? My guess is the time spent for rendering is _WAY_ bigger than the E/L calls, and you are coding a solution around a nonexistent problem...|8-{

There is another thing you should be doing to smooth out the execution. The OS will preempt your thread at its own pace. You can have a better control of this by inserting Sleep(0) between major code blocks (blocks that would take some significant amount of time); for example, if your animation thread must update 100 models, then Sleep(0) every 10 models or so. Otherwise you will find that some threads are not getting enough timeslice and you will get into a thread priority thread problem that will bite you with faster CPUs and multi-CPU machines.

Hope this helps.

-cb



Share this post


Link to post
Share on other sites
I am aware of the Sleep(0) timeslice stuff. That isn''t a problem just yet so I''m not really worrying about it. If it becomes a problem then I will place that in strategic areas.

As far as InterlockedIncrement(), I haven''t looked into it and have no clue what it does.

As far as profiling, I am 100% sure that even if I called Enter and Leave each frame, it would not be lengthy or be a problem. But that doesn''t mean I should let it sit. I have two solutions presented, so I will choose the best one.

I''m not optimizing my code to the bone yet and so this shouldn''t fall under the category of optimizing. I''m just not wasting CPU.

Share this post


Link to post
Share on other sites
Just use an int. It's a 32 bit value and on a 32 bit processor storing/reading it is atomic. If you're really paranoid, try using Events.


    
// bTimeToDie is an int that is initally set to 0.

// Once another thread set's to to be != 0 the thread dies.


while(!bTimeToDie)
{
//do something

}


or


        
// eTimeToDie is an event object that is initally nonsignaled


while(WaitForSingleObject(eTimeToDie,1) == WAIT_TIMEOUT)
{
// do something

}


See MSDN for details on creating an event object.
Also, prefer _beginthreadex over _beginthread. The later closes the thread handle before it returns.

[edited by - Solo on March 4, 2003 3:19:23 PM]

Share this post


Link to post
Share on other sites
What Solo did was what I meant when I asked about writing code in the forum. The only thing that would be worth changing my code is if while(bRunning) worked.

The only real question is wether or not sharing bRunning between the two threads could cause a problem. If the two threads can share the variable then it can be bool or int or anything.

If there is no problem having two thread share that variable, then my code is for nothing and it was fun while it lasted. If there is a problem having two threads share the variable, then my code and idea for reverse critical sections owns and will be hella faster than any other answer.

Share this post


Link to post
Share on other sites
while(bRunning) will work provided that bRunning is 32 bits or less (on a 32 bit CPU) and is not a stack based variable. This works because the statement: bRunning = 0; is simple enough to be executed atomically (can''t interrupted by another thread).

Each thread has it''s own stack so local variables cannot be shared between threads. Global variables and variables allocated on the heap can be shared between threads, just make sure operations on them are atomic (either implicitly atomic or made atomic by using a critical section or mutex).

Check the FAQ for help with adding source tags.

Share this post


Link to post
Share on other sites
I fully agree with solo.

Using WaitForSingleObject in the while loop is of course the best solution. If, on top of that, you turn the timeout into
a variable you can even control the performance quite easy without losing the ability to stop the thread anytime as clean as you get.

C ya

Share this post


Link to post
Share on other sites