At 10:39 18.04.2006 +0200, Yorh wrote:
I have a little problem with a worker thread in my app.
I have a NSWindowController class, inside it (when the window is
started) a new thread starts in a for (; ; ) infinite loop.
I need to stop the thread when the window is closed.
The idea for this is rather simple; implementation details depend
on how your communication is set up.
Basically, you need to send the thread a "please quit" command,
to tell the thread to clean up and --- you guessed it, quit
itself.
So, the basic layout is:
- set a "please do quit" global flag
- wake up the thread
- have the thread check the variable when it wakes up
Depending on your communication protocols, DO make sure
that the thread gets the wakeup signal even when it is
in the middle of processing (i.e. not currently sleeping),
either by setting up the protocol to ensure this, or by
checking the quit variable at appropiate places (in many
cases the variable should be checked BEFORE the
[Mutex lock*] call, rather than after it).
So, the thread would be something like this:
static volatile PleaseDoQuit=NO;
+(void)MyThread:(id)Dummy
{
(void)Dummy
while (!PleaseDoQuit)
{
[Condition lockWhenCondition:QUEUE_FULL];
/* process queue */
[Condition unlockWithCondition:QUEUE_EMPTY];
}
/* cleanup */
}
To shut down the thread, your main thread does this:
-(void)KillTheThread
{
PleaseDoQuit=YES;
if ([Condition tryLockWhenCondition:QUEUE_EMPTY])
{
[Condition unlockWithCondition:QUEUE_FULL];
}
}
The logic here is simple: if the lcoking doesn't
succeed the thread is still processing the queue,
so there is no need to wake it up --- it will
eventually see the PleaseDoQuit. It the condition
is "queue empty", the thread might or might not
be sleeping already, so we set it to "queue full"
just in case.
If that's to complicated to thing through, the following
will work as well:
+(void)KillTheThread
{
[Condition lockWhenCondition:QUEUE_EMPTY];
PleaseDoQuit=YES;
[Condition unlockWithCondition:QUEUE_FULL];
}
It's just wasting time on the KillTheThread because it
synchronizes with the thread...
The volatile isn't really necassary for many compilers,
but it's good practice regardless. Mutex protection for
the flag is not required.
Depending on how your program works, the above (which
is just a sample implementation) does allow the case
of some thread adding work packets which are ignored
when the quit command arrives.
If your thread uses a work-queue you can also define a special
work packet to mean "please quit" --- such as adding NSNull to
the queue.
Christian