Tight Runloop

  • Hey,

    I have some code that is getting caught in a tight in a tight run loop - it
    fulfills its function but locks the UI.

    The work needs to be performed is not thread safe and therefor needs to be
    performed on the current thread.

    Because the code is pseudo asynchronous it is scheduled to run on the
    current runloop like so;

    [object performSelector:@selector ( someFunction: ) withObject:nil
    afterDelay:0.0];

    someFunction communicates with another object and needs to wait for a
    callback so its occupying itself while it waits for the callback like so;

    do
    {
      [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode
    beforeDate:[NSDate dateWithTimeIntervalSinceNow: 2]];
    }while(somecondition);

    The callback is processed and the condition is met, the UI receives updates
    but mouse events are not processed.

    It is possible to refactor everything and have the callback respond through
    the chain to the main controller, but this does increase the complexity
    somewhat - a linear approach is easier to follow;

    Is this the correct way to 'occupy' a function or is this a great example of
    what not to do;

    cheers
  • On 9/25/07, Ricky McCrae <ricky.mccrae...> wrote:
    >
    > Hey,
    >
    > I have some code that is getting caught in a tight in a tight run loop -
    > it
    > fulfills its function but locks the UI.
    >
    > The work needs to be performed is not thread safe and therefor needs to be
    > performed on the current thread.
    >
    > Because the code is pseudo asynchronous it is scheduled to run on the
    > current runloop like so;

    [snip]

    [object performSelector:@selector ( someFunction: ) withObject:nil
    > afterDelay:0.0];

    I am no Runloop expert but guess the above should be written like this

    [object performSelector:@selector ( someFunction ) ];

    S
  • On Sep 25, 2007, at 5:11 AM, Ricky McCrae wrote:

    >
    > someFunction communicates with another object and needs to wait for a
    > callback so its occupying itself while it waits for the callback
    > like so;
    >
    > do
    > {
    > [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode
    > beforeDate:[NSDate dateWithTimeIntervalSinceNow: 2]];
    > }while(somecondition);
    >
    > The callback is processed and the condition is met, the UI receives
    > updates
    > but mouse events are not processed.
    >
    >
    > Is this the correct way to 'occupy' a function or is this a great
    > example of
    > what not to do;
    >
    >
    This doesn't seem to be a great way to do this as the main threads
    run loop is already running, and you function just hijacked it and
    started it running again. So, I think the behavior is undefined as
    your seeing. Plus to get this working, I think you would have to not
    re-run the  run loop but take over event processing. What you are
    trying to do suggest that someFunction should be run in a thread as
    it will have its own run loop and won't block the rest of the
    application while it waits. Since you have an event, the callback,
    you might want to reconsider your design to be asynchronous, such
    that you start the process in someFunction and then your callback
    finishes it. So, ask yourself, why does someFunction need to wait?

    Brian
  • On 25 Sep 2007, at 12:11, Ricky McCrae wrote:

    > The work needs to be performed is not thread safe and therefor
    > needs to be
    > performed on the current thread.

    [snip]

    > someFunction communicates with another object and needs to wait for a
    > callback so its occupying itself while it waits for the callback
    > like so;
    >
    > do
    > {
    > [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode
    > beforeDate:[NSDate dateWithTimeIntervalSinceNow: 2]];
    > }while(somecondition);
    >
    > The callback is processed and the condition is met, the UI receives
    > updates
    > but mouse events are not processed.

    The problem with this kind of code is that the run loop doesn't
    always work the way you expect (as you've discovered).  You also run
    the risk of having to deal with re-entrancy.

    Basically, the problem you're having here is that you're trying to
    mix event-driven programming with linear blocking programming.  The
    two don't really mesh together very well, so it's better either to
    put your blocking code on a separate thread, or write all of your
    code in an event-driven fashion.

    It's normally *much* easier to farm the work off to a separate
    thread, then just have the thread inform the main thread when it's
    done.  What are you actually doing in your code that you feel can't
    be done that way?  Remember, "thread safety" *normally* refers to the
    ability of code to run simultaneously on more than one thread, not to
    whether it can be invoked at all from a separate thread.  Code that
    can't run *at all* on a separate thread does exist but it's very much
    less common.

    Kind regards,

    Alastair.

    --
    http://alastairs-place.net
previous month september 2007 next month
MTWTFSS
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Go to today