0

I want to implement a while loop that exits either when a particular condition is met, or when a timer times out. If I just start the timer (to set an object variable on timeout), and then start the while loop (checking the object variable), it doesn't work, because the timer never times out.

I've tried 3 of the solutions suggested in How to wait for a thread to finish in Objective-C to make the loop run in a separate function on another thread, but they fail in various different ways. I have not yet managed to get a test run where the timer times out.

The simple implementation was

//object variable
BOOL m_readTimedOut;

- (void) someFunction
{
m_readTimedOut = NO;
float timeoutS = 0.1;

//Start the timer
SEL readTimeoutSelector = sel_registerName("onReadTimeout:");
    [NSTimer scheduledTimerWithTimeInterval:timeoutS
                                            target:self
                                            selector:readTimeoutSelector
                                            userInfo:nil
                                            repeats:NO];

int numBytesToRead = 1;
BOOL exit = NO;
int counter = 0;
    while ((counter < numBytesToRead) && (exit == NO))
    {

        @try
        {
            @synchronized (readBufferLock)
            {
                //m_readBuffer is an object variable that can be altered on another thread
                if ([m_readBuffer length] > 0)
                {
                    //Do stuff here
                    counter++;
                }
            } //end synchronised
        }
        @catch (NSException *exception)
        {
            //Log exception
        }

        if (counter == numBytesToRead || m_readTimedOut == YES)
        {
            exit = YES;
        }
    } //end while
}


- (void)onReadTimeout:(NSTimer *)timer
{
    NSLog(@"Read timer timed out");
    m_readTimedOut = YES;
}
user1725145
  • 3,993
  • 2
  • 37
  • 58

1 Answers1

1

Just a try on the timed exit only - how about

NSDate * start = [[NSDate alloc] init]; // When we started

while ( counter < something )
{
  // do stuff ...

  // Check time
  NSDate * now = [[NSDate alloc] init];

  // Been here more than 10s since start
  if ( [now timeIntervalSinceDate:start] > 10 )
  {
    // Timed exit
    break;
  }
}
skaak
  • 2,988
  • 1
  • 8
  • 16
  • I will try this, thank you. I did figure out that the timer should be on its own thread, while the loop runs on the main thread, but I haven't managed to implement this correctly. Going to try your suggestion now instead... – user1725145 Jun 12 '20 at 15:00
  • This is just single threaded and just checks the elapsed time whenever ```do stuff``` completes. I hope it helps but if you have some timing requirement on ```do stuff``` itself it can be a lot more complex. I suggest, however, that you make the ```do stuff``` bit so simple that it will not block, at least not for long, and that you will thus check the time frequently. – skaak Jun 12 '20 at 15:13
  • It works! Thank you, thank you, thank you. Is this a "more Objective-C" style solution? – user1725145 Jun 12 '20 at 15:21
  • Also, I haven't found anywhere that really explains how Obj-C timers work. – user1725145 Jun 12 '20 at 15:30
  • Thanks - glad I could help. Objective-C? Nah this is common practice especially in background threads where you may check time or even a flag for cancel. The way in which you measure time will differ between languages. Objective-C timers is another story but overkill here **I think**. – skaak Jun 12 '20 at 15:44
  • Note especially that the tricky part is of course the ```do stuff```. Even with the timed exit, if that takes 20 minutes to complete you'll be stuck in the loop for 20m. So you need to write that portion carefully so that it does not get stuck for too long. – skaak Jun 12 '20 at 15:48
  • Timers are so easy in higher level languages that one just uses them without thinking too much about it - so perhaps it's a more low level language style. I don't mind if timeout happens when I'm doing something - it's only there only to catch the cases where there's nothing to do, iyswim. – user1725145 Jun 15 '20 at 07:56