Yield in a Cocoa while loop
I'm trying to rework the event handling mechanism in my engine, with the goal of getting it to stop hog 100% CPU when it can. I realize that I should be on a timer, but due to the way its Win port works and the general structure of the engine, this isn't likely to happen anytime now.
I need to enter a function and not return until the application is ready to quit. Right now I do this by trapping myself in a while loop calling
Unfortunately, this burns through cycles like nothing else since the main thread never yields to other apps. One simple solution would be to add an explicit yield for a fraction of a second after each rendered frame, but I haven't found a way to make Cocoa suspend itself. So, my primary question is if there's a simple, overlooked way to make the run loop run and yield? Would calling runUntilDate: "now + 1/60th second" actually suspend the thread for a while?
Another solution would be to lock myself into a new run loop with a timer that calls my update function at the desired interval - does this sound possible and desirable?
Thanks, as always.
I need to enter a function and not return until the application is ready to quit. Right now I do this by trapping myself in a while loop calling
Code:
[[NSRunLoop currentRunLoop] runUntilDate: distantPast];
event = [NSApp nextEventMatchingMask: eventMask
untilDate: distantPast
inMode: NSEventTrackingRunLoopMode
dequeue: YES];
Unfortunately, this burns through cycles like nothing else since the main thread never yields to other apps. One simple solution would be to add an explicit yield for a fraction of a second after each rendered frame, but I haven't found a way to make Cocoa suspend itself. So, my primary question is if there's a simple, overlooked way to make the run loop run and yield? Would calling runUntilDate: "now + 1/60th second" actually suspend the thread for a while?
Another solution would be to lock myself into a new run loop with a timer that calls my update function at the desired interval - does this sound possible and desirable?
Thanks, as always.
I'm not sure how well it would work, but one thing to try would be to call usleep with a small interval between event polls. That should at least get your CPU usage under control.
You can also wrap your main loop around a call to select() (on Windows, this is WaitForMultipleObjectsEx or similar). This is essentially what SDL and Qt do under the hood.
If you lock everything to say.... 60fps, you can easily add a bit of timing and a usleep for the extra time.
Code:
while (playing) {
NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate];
if (currentTime - _timeOfLastFrame >= 1.0 / _maxNumberOfFramesPerSecond) {
run a frame
} else {
double timeLeft = ((1.0 / _maxNumberOfFramesPerSecond) - (currentTime - _timeOfLastFrame));
usleep(1000000 * timeLeft);
}
}
If you're drawing on your main thread, just turn on vsync

Wow, those are some cool ideas - I have to experiment with them to see what works. Just one question to Keith: I am vsynching, but that only seems to synch the actual page flip to the retrace, not actually block on it? I had hoped for VBL blocking, but since it doesn't seem to take, I started to look for run loop solutions...
Perhaps you have triple-buffering enabled?
My bad, I had forgot that I was turning the VBLSync off with a compiler -D define deeper down than where I was looking. Thanks.
Possibly Related Threads...
Thread: | Author | Replies: | Views: | Last Post | |
Proper game update loop in Cocoa? | LoneIgadzra | 13 | 11,055 |
May 30, 2008 05:49 AM Last Post: ThemsAllTook |
|
Cocoa Event Loop/NSTimer revisited | Fenris | 6 | 7,991 |
Oct 29, 2005 11:27 PM Last Post: maaaaark |
|
Game Loop in Cocoa | robmcq | 9 | 9,477 |
Sep 27, 2005 10:49 AM Last Post: akb825 |