NSIdleEvent ?

Discussion in 'Mac Programming' started by zeppenwolf, May 9, 2010.

  1. zeppenwolf macrumors regular

    zeppenwolf

    Joined:
    Nov 17, 2009
    #1
    Is there anything similar to OS9 / carbon "idle" events in cocoa? I sure can't find it in the cocoa events dox...

    Or a relatively easy way to mimic them? What I'm really after is a way to judge how much of a huge computation I should do based on how much the user is doing elsewhere. Thx.
     
  2. jared_kipe macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #2
    First off why, second off NSThread has -setThreadPriority: method to play nicer with other running operations.
     
  3. zeppenwolf thread starter macrumors regular

    zeppenwolf

    Joined:
    Nov 17, 2009
    #3
    jared_kipe> First off why

    I'm updating a classic app which does a monster computation, (in response to "new"). Idle events, clock ticks, (and of course frontmost), are looked at to judge how greedy to be in the old app. I can handle figuring out frontmostB(), but the idle stuff is not happening.

    So, a couple reasons why: One, I guess laziness, but it would be nice to keep the same paradigm, if not the same exact code, while I'm updating the whole UI thing and UI events to carbon or cocoa depending on compile, (got that stuff mostly done). Two, beyond playing nice with others, it's pretty important that the app itself stays responsive in case the user does something in menus or open windows while the monster computation is going on. How that's supposed to work with the new 'events are callback-only' type thing in cocoa I just don't see.

    >second off NSThread has -setThreadPriority: method to play nicer with other running operations.

    I have the feeling you're going to say that I need to use NSThread, period, no other, like "normal" way to go? I probably shouldn't say "normal"-- I have no idea what's normal anymore! :) Thx.
     
  4. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #4
    Well you could schedule a method to run every run loop and do a little bit in each loop. But, in all honesty, that's a really nasty solution and you'd be better with a thread...
     
  5. jared_kipe macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #5
    Generally speaking, if this "massive calculation" was massive back in OS9 maybe it can be computed in much much less time these days by just letting it go for it. That way as computers get faster it will be completed with less time.

    To minimize your CPU footprint if you want to stay out of the way of the user you could do something and then sleep after it.

    For example, if left unbound this will use 100% cpu usage. But with the sleep in it, it drops to about 50% on my computer.

    Code:
    #import <Foundation/Foundation.h>
    
    void sync() {
    	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    	NSTask *unison;
    	unison = [[NSTask alloc] init];
    	[unison setLaunchPath:@"/bin/ls"];
    	[unison launch];
    	//[unison waitUntilExit];
    	[unison release];
    	[pool drain];
    }
    
    int main (int argc, const char * argv[]) {
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    	
        int i;
        for (i=1; i<=5e4; i++) {
    		sync();
    		if(i%2==0)sleep(1);
        }
        [pool drain];
        return 0;
    }
    
     
  6. Sydde macrumors 68020

    Sydde

    Joined:
    Aug 17, 2009
    #6
    The Mach kernel in OS X has this little feature that you can access from the terminal with "renice" - it parcels out CPU time to all the running processes in little slices, so you really have no need to worry about "playing nice" with the other apps as you would have in Classic Mac OS.

    You can easily fire of a thread any time you want to do something in the background, just set up parameters that your main run loop (the one that handles UI stuff) can check so that it is not trying to deal with incomplete data. When the thread is done, it can simply exit and you can start up a new one any time you need heavy background stuff done. All you really have to remember is to keep the main thread from trying to use or modify unfinished work.

    Alternately, you can use NSConditionLock to set your thread up for queued operations, letting it sit idle at the lock while it is waiting for work. This works well, but it can be a bit of a PITA to manage.
     
  7. Catfish_Man macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #7
    setpriority() is the call for modifying the priority of a process programmatically.

    In general I agree with others that slicing your work up and doing a small chunk each runloop iteration is a "good" way to do things. If you need uninterrupted work while maintaining responsiveness, threading is the way to go.
     
  8. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #8
  9. zeppenwolf thread starter macrumors regular

    zeppenwolf

    Joined:
    Nov 17, 2009
    #9
    Ok guys, it was all interesting, but I guess the verdict's in: I need to get hip with NSThread. Thanks for all the brainwork.

    Just to end this NSMacForumsThread on a humorous note, here's something I found in the man page of 'renice':

    BUGS
    Non super-users can not increase scheduling priorities of their own pro-
    cesses, even if they were the ones that decreased the priorities in the
    first place.


    Heh.
     
  10. Sydde macrumors 68020

    Sydde

    Joined:
    Aug 17, 2009
    #10
    If on a modern computer you are doing so much work that there is a perceptible delay creating/opening a document, you should consider how quickly you can get a usable document in front of them and be able to fill in the underlying material in the interim. This might mean a delay with their initial edit, you have to decide which is preferable, a delay accessing or a delay upon starting to edit.

    One possibility, when you have concluded that there will be a lag and you have done all the optimization realistically feasible to trim it to the minimum, is to provide a progress bar. If the user does have to wait, they should at least see that something is happening.
     

Share This Page