Welcome to the MacNN Forums.

If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

You are here: MacNN Forums > Software - Troubleshooting and Discussion > Developer Center > EXTRA! Main Thread Bullies Innocent Thread!

EXTRA! Main Thread Bullies Innocent Thread!
Thread Tools
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status: Offline
Reply With Quote
Jun 10, 2003, 10:09 PM
 
Observe the following code:

Code:
[self stopReading:nil]; while(state!=0){ NSLog(@"Waiting for stop state. Current State = %i", state); }
The stopReading: method executes asynchronously in its own thread. It's job is to stop a process and to then set an instance variable named "state" to "state=0" to indicate that the process has stopped. This works fine, since I can verify a responsive UI while it the thread executes.

Now here it's were it gets a bit more interesting. The while loop below never exits.
This is because the state variable in question is never updated in the background. My guess is that the loop starves the background thread.

I find this a bit odd since I thought that background process was going to get some CPU time.

Any comments?

Thanks!

     
Professional Poster
Join Date: Nov 2000
Location: Tasmania, Australia
Status: Offline
Reply With Quote
Jun 10, 2003, 10:41 PM
 
Edit:

OK, looks like I was completely off track.
(Last edited by Brass; Jun 10, 2003 at 11:47 PM. )
     
Addicted to MacNN
Join Date: Nov 2002
Location: Seattle, WA
Status: Offline
Reply With Quote
Jun 10, 2003, 11:01 PM
 
no, I do use threads and that is definitely wonky. I use shared instance variables all the time (most commonly BOOL cancelled = NO;), and I also am acutely aware that different threads in the same app do not have memory protected from each other.

what was the exact code you used to branch off the new thread? What happens when you fill stopReading with NSLogs? or when you debug and put stop points in the stopReading thread? are you sure that method is actually running?

also, what if "state" is already used by something. try another less likely var name
     
Professional Poster
Join Date: Dec 2000
Location: Chicago, Illinois
Status: Offline
Reply With Quote
Jun 10, 2003, 11:09 PM
 
I'd have to see how your spawning your thread and everything, but the only thing that comes to mind is: are you properly locking your global instance variables when you're changing them? I think weird things can happen if one thread is reading a variable at the same time your changing it.

Matt Fahrenbacher
     
Mac Elite
Join Date: Sep 2000
Location: Norfolk, Va
Status: Offline
Reply With Quote
Jun 10, 2003, 11:14 PM
 
Using the debugger, with a breakpoint in your stopReading method where it is supposed to set state to 0, does it ever get there?
you are not your signature
     
DaGuy  (op)
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status: Offline
Reply With Quote
Jun 10, 2003, 11:15 PM
 
Let me do some additional checking. I'll post again soon.
     
DaGuy  (op)
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status: Offline
Reply With Quote
Jun 10, 2003, 11:41 PM
 
I screwed up. Cocoa is beautiful!

The stopReading: method doesn't set the "state" instance variable. My boo boo. The variable is set by an NSTimer which polls several combinations of instance variables to determine the application's state. The NSTimer is the heart beat of the state machine.

The problem is that the timer runs in the main thread. Since the loop also runs in the main thread, it blocks the timer from firing and updating the state variable.

Multithreading is a tricky business. Sorry guys. I should've paid more attention. I will run the timer in a different thread.

     
Addicted to MacNN
Join Date: May 2001
Location: Cupertino, CA
Status: Offline
Reply With Quote
Jun 12, 2003, 02:09 PM
 
Yes, the timer should be in another thread. While we're at it, one should never write loops like the above, because they're just wasting CPU cycles (this is called busy waiting). I'm assuming you probably just wrote that for debugging purposes though. It's also advisable to synchronize access to that state variable, since it's shared by multiple threads...
     
Mac Elite
Join Date: Sep 2000
Location: Norfolk, Va
Status: Offline
Reply With Quote
Jun 12, 2003, 02:44 PM
 
In my threads, I have a while loop that exits when shouldThreadDie = YES. Other functions check up on isThreadRunning from time to time or in while loops of their own.
Is this an acceptable method, or am I wasting time too?
What's the recommended way?
you are not your signature
     
Addicted to MacNN
Join Date: May 2001
Location: Cupertino, CA
Status: Offline
Reply With Quote
Jun 12, 2003, 03:26 PM
 
The general idea is that a thread that's doing nothing but constantly polling a shared variable should be put to sleep and be notified when the variable changes. The way you usually do this is with a monitor (a condition variable and a lock). The pseudo-code is something like so:

Code:
acquire lock while not CONDITION wait on shared variable do your stuff... ... ... notify one or all threads waiting on shared variable release shared variable's lock
What this lets you do is go to sleep while the variable remains unchanged. Conditional variables allow a thread to add itself to a wait queue AND to release a lock atomically, so a thread that has to wait can simply sleep and release the lock, allowing other threads to attempt to acquire the lock and do something useful with the variable. When another thread has changed the variable, it should notify one or all of the threads waiting on the condition. When the above thread is awakened, it would reacquire the lock and then resume execution within the while loop.

See Apple's documentation for information about how this is implemented in Cocoa.

Here's an example in Java, though please note that Java's implementation is a little weird because every object implicitly has a built in monitor:

Code:
... in a thread class ... // A shared variable public String whereAmI = null; public void run() { synchronized (whereAmI) { while (whereAmI == null) whereAmI.wait(); System.out.println ("I know where I am!"); System.out.println ("I'm in " + whereAmI); whereAmI.notifyAll(); } }
Keep in mind that this is a pretty useless thread. There are also some situations where you can change the while above to an if, depending on the type of monitor being used and the type of condition you are waiting for.
     
DaGuy  (op)
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status: Offline
Reply With Quote
Jun 13, 2003, 03:08 PM
 
Thanks for the discussion. I definitely got a more educated perspective going forward.

     
   
Thread Tools
Forum Links
Forum Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Top
Privacy Policy
All times are GMT -5. The time now is 03:41 PM.
All contents of these forums © 1995-2011 MacNN. All rights reserved.
Branding + Design: www.gesamtbild.com
vBulletin v.3.8.7 © 2000-2011, Jelsoft Enterprises Ltd., Content Relevant URLs by vBSEO 3.3.2