How to wait within a thread

Hi there,
I have a question about threads and pausing or waiting within a thread. In my case I’ve made a c++ game development for Android phones on windows (visual c, eclipse). It’s multithreading. In the main thread I do all the SDL stuff like rendering etc. In a second thread I meanwhile calculate the game logic for the next iteration. Thread 2 takes only a few ticks and then has to wait until the next iteration starts. If I let wait the thread with a simple slope construction, the battery consumption on an android phone is far too high and the phone gets hot. So I changed my code : I end the calculation thread, when it has done it’s work. So 90% of the time, there is only the main thread working. And every iteration I start a new game-logic-calculation thread. Battery consumption and temperature of the phone are ok now.

Is that the right way to do it?

I’m not sure, if that doesn’t cause other issues. Creating and killing 60 threads per second can produce other side-effects, can’t it ?

I use SDL_SemWait in a similar situation and that seems to be OK, at least I haven’t noticed any resulting issues. I certainly hope that it waits in an efficient way with negligible CPU consumption.

Richard.

And every iteration I start a new game-logic-calculation thread.

I’m surprised that isn’t really inefficient, honestly.

My first suggestion would be: if the game logic only takes a tiny bit of time every frame, are you sure you need a thread for this? It’s very possible that your main thread is going to spend most of its time waiting for the GPU to swap buffers…if rendering takes you a few milliseconds, and game logic takes a few milliseconds, it’s possible your main thread is doing literally nothing for double that time and you still clear 60fps. If that’s the case, just simplify your code and make it single threaded: it’ll be way easier to read and work with, no risk of race conditions or sync issues, and it’s just using CPU time that was wasted anyhow. Instead of spinning a thread to run myGameLogic(), just call myGameLogic() directly at that point.

If you need that thread, you should probably use an SDL_cond or SDL_sem, which will make your thread sleep until you signal it in another thread, telling it that it’s time to do more work. But I’d strive to remove the second thread entirely, honestly.

Hi there, thanks for your reply.
Yes, I unfortunately need the second thread. My App was single thread first. But the main thread needs nearly the whole iteration for rendering. The game logic thread needs in most of the iterations only a few ticks, but in some iterations more. With multithreading the app runs fluidly, without it jerks.
I’ll give _wait + _cond a try.
Thank you for the tip.

1 Like

I tried it out now and made a test with SDL_CondWait and SDL_CondSignal. My second thread for game logic is created once at startup of the app. When it’s done it’s work it waits in SDL_CondWait until the mainthread has done rendering and signals via SDL CondSignal that the next Iteration can be calculated.
Works nearly as well as my first method, creating and detaching the second thread every iteration. With one difference: Battery consumption on Android phone is much higher. CPU consumes 350 - 400 mV instead of 200-250 mV.
Meaning : Waiting in second thread instead of killing it costs.
Am I right or did I something wrong ?
I can’t believe there isn’t a resource-friendly way to make a thread waiting.

How are you waiting on the condition? If it’s using the pthread implementation internally, it’s susceptible to spurious wakeups (i.e. the thread may wake up and go about its business, unless directed otherwise). So just SDL_CondWait() is not enough, you need a loop re-checking some predicate every time the thread wakes up. The example on the wiki shows how to do this, even though doesn’t really explain why.

This is my “wait”-slope for the second thread:

while ( TAppUpd::I()->GetRunningState() )
{
	SDL_LockMutex( TThreader::appUpdaterThreadLock );
	SDL_CondWait( TThreader::appUpdaterThreadGo, TThreader::appUpdaterThreadLock );
	SDL_UnlockMutex( TThreader::appUpdaterThreadLock );
    }

and the main threads sends Signal, that a new iteration begins via:

SDL_CondSignal( TThreader::appUpdaterThreadGo );

That’s not right :slight_smile: It should be something like this:


while ( TAppUpd::I()->GetRunningState() ) // I assume this is the terminator for otherwise infinite loop?
{
    SDL_LockMutex( TThreader::appUpdaterThreadLock );
    // wait until main thread really signals us
    while( !NeedNewData )
        SDL_CondWait( TThreader::appUpdaterThreadGo, TThreader::appUpdaterThreadLock );
    NeedNewData = false;
    SDL_UnlockMutex( TThreader::appUpdaterThreadLock );
    // calculate new state...
}

// and main thread:

SDL_LockMutex( TThreader::appUpdaterThreadLock );
NeedNewData = true;
SDL_CondSignal( TThreader::appUpdaterThreadGo );
SDL_UnlockMutex( TThreader::appUpdaterThreadLock );

Hi Stan,

thank you very much. I think I understand SDL_CondWait now better. I did how you told and it works.

But my initial problem is with this solution still the same: Battery consuption on my Android phone = CPU consumes 400 mV.

My old and inelegant solution = Killing and starting the gamelogic thread every iteration = CPU consumes only 250 mV

Any further ideas how to let a thread wait more resource-friendly ?

Michael

Hm, that is strange. Perhaps it depends on the concrete implementation of those synchronization primitives. You could try another one, i.e. a semaphore (SDL_sem) as suggested by @icculus.
Another option to try is synchronization via a pair of mutexes, where your logic thread waits on mutex A until main thread sets a flag, then main thread waits on mutex B until until logic thread resets that flag; changing the priority of the logic thread while it waits (via SDL_SetThreadPriority)…