Re: NSConditionLock question
Re: NSConditionLock question
- Subject: Re: NSConditionLock question
- From: Chris Kane <email@hidden>
- Date: Sat, 25 Aug 2001 18:59:17 -0700
On Friday, August 17, 2001, at 03:22 PM, Sarwat Khan wrote:
I've run into a bit of deadlock with this bit of code,
[_queueLock lock];
if ([_queue count] == 0 && _isClosed == FALSE)
{
[_queueLock unlock]; //bad!
[_queueLock lockWhenCondition:kCondition_hasData];
}
What I want is to be able to relock on another condition. The problem
here is that isClosed is set to true just after the unlock. I've been
able to implement this using pthread's mutex stuff, which has
pthread_cond_wait(condition, mutex), which will unlock the mutex and
wait for the condition (and re-lock the mutex when it returns).
Trouble here is that you're using the NSConditionLock in the usual
pthread_cond pattern. Or another way to put it is that you're using the
NSConditionLock like both the mutex and the condition in the usual
pthread_cond pattern.
For NSConditionLock, the conditions are usually "flattened" into a set
of defined ints. For example, if we ignore closing or full conditions,
to dequeue:
[_queueLock lockWhenCondition:HAS_ELEMENTS];
... remove element ...
[_queueLock unlockWithCondition:([_queue count] > 0 ?
HAS_ELEMENTS : IS_EMPTY)];
to enqueue:
[_queueLock lock];
... put element ...
[_queueLock unlockWithCondition:HAS_ELEMENTS];
However, when you want to want more inclusive (OR'd) conditions, that's
where NSConditionLock falls down. The condition test is == with the
desired condition and the actual condition. Sure you can encode all the
possible meaningful states in integers, and the unlocking end of things
is easy enough.
But when you want to "lockWhen" X or Y or Z, you have trouble. I
personally think it's a not very useful class. Something taking a
predicate method/function would be more general, but more complicated to
use. Even a lockWhenNotCondition: would allow more things. In this
case, adding the full condition:
DEQUEUE
[_queueLock lockWhenNotCondition:IS_EMPTY];
... remove element ...
[_queueLock unlockWithCondition:([_queue count] > MIN_ELEMS ?
HAS_ELEM : IS_EMPTY)];
ENQUEUE:
[_queueLock lockWhenNotCondition:IS_FULL];
... put element ...
[_queueLock unlockWithCondition:([_queue count] < MAX_ELEMS ?
HAS_ELEM : IS_FULL)];
since we'd want to lock on two of the three conditions in each case.
With -tryLockWhenCondition:CLOSED you can do some things with a CLOSED
state as well.
But your full general case is beyond NSConditionLock.
Chris Kane
Cocoa Frameworks, Apple