of WaitNextEvent and Thread Priorities and Ceiling Whacks

Posts: 145
Joined: 2002.06
Post: #1
In 9 everything is easy: don't call WNE unless your life depends on it Smile.

But I remember hearing a while back on mac-games-dev that in X, not calling WNE results in the thread scheduler downgrading your thread's priority. IIRC the outcome of this whole discussion was that when in X, unless you're using CarbonEvents, you should call WaitNextEvent with a sleep time of 1. Does anyone have supporting evidence for this?

"He who breaks a thing to find out what it is, has left the path of wisdom."
- Gandalf the Gray-Hat

Bring Alistair Cooke's America to DVD!
Quote this message in a reply
Posts: 5,143
Joined: 2002.04
Post: #2
It was never quite cleared up precisely what happens to you if you don't give the OS time, but enough people report enough bad stuff happening for me to believe them Smile. One thing you can rely on is getting a spinning beach-ball cursor.

On OS 9, calling WaitNextEvent(0) was also a reasonable option -- the system got time, but you got control back ASAP. Many games successfully used this route. OS X, however, has a special case on WNE(0) to replace the 0 with a much longer sleep time. This was an attempt to "fix" many older applications' CPU usage without forcing a recompile.

If you call WNE(1), you should avoid the special case, and avoid any penalization for not giving the OS time. However, you will not, under any circumstances, be returned control before that 1/60th of a second is up, even if nobody else needs the CPU time.

The solution to all of this is, of course, Carbon Event timers. Set up a timer to fire every millisecond, so you'll be called back as often as the scheduler allows, and either pass a very long sleep time to WNE, or use RunApplicationEventLoop. The very high-frequency timer means that if nothing else requires the CPU, you will get it. Because you spend all the time you can blocked in RAEL, you won't be punished.

If you find that even with Carbon Event timers and RAEL you're still getting a jerky frame-rate when other programs are running, there is a way to put yourself on fixed-frequency scheduling. That means that, although you don't get any more CPU time than normal, you are guaranteed to get it regularly. Most people won't find this necessary, but some people have reported good success with it. You'll need to search the archives of the mac-games-dev list to find out how: http://lists.apple.com Smile

There's also a very detailed discussion of precisely how the OS X scheduler works on that list.
Quote this message in a reply
Post: #3
I am currently calling ReceiveNextEvent(0, NULL,0,...) to give me more time (timeout = 0), would I be penalized for this too?
Quote this message in a reply
Posts: 446
Joined: 2002.09
Post: #4
CarbonEvents with RNE works extremely well for me in both OSX and OS9. Here's the event loop (more or less) from a project I'm currently working on:
while (!gQuit)
    if (gInBackground)
        wait = kEventDurationSecond/100;
        wait = kEventDurationNoWait;

    ReceiveNextEvent(0, NULL, wait, true, &theEvent);
    if (theEvent)
        SendEventToEventTarget (theEvent, theTarget);        
        ReleaseEvent (theEvent);
    /* Run a frame here, using the time delta since the last frame */
This reports up to 100% usage in ProcessViewer while in front (basically uses as much as it needs), and 0-5% in the background. You can actually take it one step further and use a wait of "kEventDurationForever" if the app is hidden, but that could mess up stuff in the main loop that requires semi-regular updates (like networking). I've haven't seen any OSX scheduler "bullying" problems (or beachballs) using this loop.

I found that RAEL with a timer running frames is *too* generous to background tasks and generally unreliable. RAEL is easier to use however, and handles nitty-gritty stuff that you need to take care of manually with RNE (apple events, menus, etc.) so it should be fine for puzzle-type games where a consistant frame rate isn't that important.
Quote this message in a reply
Post: #5
OK, good. That is almost exactly what I have been doing, though I hadn't thought to change the wait while in the background. I will add that.

I'm happy to hear that my solution isn't being punished Smile
Quote this message in a reply
Post Reply