iDevGames Forums
Yield in a Cocoa while loop - Printable Version

+- iDevGames Forums (http://www.idevgames.com/forums)
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: Game Programming Fundamentals (/forum-7.html)
+--- Thread: Yield in a Cocoa while loop (/thread-2870.html)



Yield in a Cocoa while loop - Fenris - Dec 27, 2007 08:48 AM

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

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.


Yield in a Cocoa while loop - ThemsAllTook - Dec 27, 2007 10:27 AM

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.


Yield in a Cocoa while loop - mattz - Dec 27, 2007 11:38 AM

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.


Yield in a Cocoa while loop - SethWillits - Dec 27, 2007 01:21 PM

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);
    }
}



Yield in a Cocoa while loop - OneSadCookie - Dec 27, 2007 01:55 PM

If you're drawing on your main thread, just turn on vsync Wink


Yield in a Cocoa while loop - Fenris - Dec 27, 2007 02:41 PM

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...


Yield in a Cocoa while loop - OneSadCookie - Dec 27, 2007 10:09 PM

Perhaps you have triple-buffering enabled?


Yield in a Cocoa while loop - Fenris - Dec 28, 2007 02:00 AM

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.