• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: A couple NSRunLoop questions
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: A couple NSRunLoop questions


  • Subject: Re: A couple NSRunLoop questions
  • From: Ken Thomases <email@hidden>
  • Date: Mon, 4 May 2009 22:12:49 -0500

On May 4, 2009, at 8:54 PM, Miles wrote:

1) I have a timer on a run loop. Every so often I invalidate the timer which
as I understand it should remove the run loop as well. At a later time I
start a new run loop (by calling the same method as before), then invalidate
that timer after a while, and repeat.

I think you are confused about the nature of run loops.

Every thread has exactly one run loop associated with it. You don't create run loops nor do you remove them.

You can schedule a timer on a run loop. Invalidating the timer removes it from the run loop. This doesn't affect the lifetime of the run loop. The run loop existed before and continues to exist after.


When I pause the debugger after this happens a few times I notice that
sometimes the run loop threads have been successfully removed and sometimes
not. I should only ever see one at most, but sometimes I see two or more.
The timer in the extra threads hanging around are not running because it
would be obvious in my app if that was happening.

Again, you are confused. There's no such thing as a "run loop thread". There are threads. They all have a run loop. It is not true that there should only ever be one. There should be as many threads as the program and/or frameworks are using. However, a thread may or may not be actively running its run loop at any given time. If you see threads whose stack traces show run loop-related functions, then those functions are running their run loops. In all probability, they are blocked in their run loop waiting for something of interest to happen. This is normal.


These threads were not necessarily created directly by you (and definitely weren't created by your timer). Some may have been created by the frameworks for their own purposes.

Your timer exists from the time you created it until all ownership responsibilities for it are released. When you schedule a timer on a run loop, the run loop retains it. When you invalidate the timer, the run loop releases it. You may also have an ownership responsibility, depending on how you created the timer and if you retain it explicitly. Seeing other threads in the debugger, even other threads running their run loops, in no way indicates that your timer still exists.


Here's the important code:

[NSThread detachNewThreadSelector:@selector(startTileAnimation:)
toTarget:animationHelper withObject:nil];

So here you're actually creating a new thread. That's above and beyond what you previously discussed with timers.



-(void)startTileAnimation:(id)sender {
   NSLog(@"start loop");

NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
myRunLoop = [NSRunLoop currentRunLoop];
animationTimer = [NSTimer
scheduledTimerWithTimeInterval:ANIMATION_STEP_FREQUENCY target:self
selector:@selector(doTileAnimation:) userInfo:nil repeats:YES];
[myRunLoop addTimer:animationTimer forMode:NSDefaultRunLoopMode];
[myRunLoop run];
[autoreleasepool release];
}

The only thing this thread is doing is letting a timer fire. Is there a reason you're not doing this on the main thread?


Also, you seem to be working with GUI stuff. You can do some GUI stuff from background threads, but it presents some complications. Again, you're probably better off doing this on the main thread.


-(void)stopTileAnimation {
   if(animationTimer != nil) {
       NSLog(@"stop loop");

       [animationTimer invalidate];
       animationTimer = nil;
   }
}

There's no guarantee that removing all of _your_ input sources and timers from a run loop will cause -[NSRunLoop run] to exit. See the documentation for that method.


Also, if you're invoking -stopTileAnimation from a thread other than the one with your timer on it, that's not safe. There's a pretty clear warning about exactly this in the documentation for -invalidate.

If you're seeing your threads sticking around after you've invoked - stopTileAnimation, these problems are probably why.


2) My second question is, from within that run loop, is it safe to make a
copy of an array that’s in the main thread like this?


NSMutableArray *tmp = nil;
NSLock *theLock = [[NSLock alloc] init];
if( [theLock tryLock] ) {
       tmp = [NSArray arrayWithArray:animatingTilesArray];
       [theLock unlock];
}

No, that's not how locks work. In order to synchronize access to a given object between threads, those threads need to lock the _same_ lock. The above code creates a new lock, which, since it's local, can't possibly be shared with anything else. Therefore, that lock is useless for synchronizing anything.


Typically, the lock would have a similar scope and lifetime to the array object which it's guarding. That is, if animatingTilesArray is an instance variable, the lock would also be one. Then, _all_ access to the array would have to be guarded by the lock. You can't just lock the lock when you copy from the array, you have to lock it when you mutate the array, or enumerate the array, or pick a specific element from it, etc. A good way to do this is to create a class specifically to manage the array and all accesses to it. An even better way would be to avoid accessing this array from multiple threads in the first place.

Don't take this the wrong way, but you seem to be in over your head. Threading is a very complicated topic. If you can avoid it, you should. If you have to use it, you should read all of the basic introductory material you can get your hands on, and wade in slowly rather than diving it.

Cheers,
Ken

_______________________________________________

Cocoa-dev mailing list (email@hidden)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


References: 
 >A couple NSRunLoop questions (From: Miles <email@hidden>)

  • Prev by Date: Re: Cocoa-dev Digest, Vol 6, Issue 661
  • Next by Date: Re: Does Cocoa layer translate Objective-C objects to C++?
  • Previous by thread: Re: A couple NSRunLoop questions
  • Next by thread: Load TableViews One TableView At a Time.
  • Index(es):
    • Date
    • Thread