[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: NSConditionLock
From: |
David Chisnall |
Subject: |
Re: NSConditionLock |
Date: |
Mon, 12 Dec 2011 15:31:34 +0000 |
I think you are misunderstanding what NSCondition does.
The -wait method releases the lock and waits for it to be signalled. When it
is signalled, it atomically acquires the lock when the thread that owns it.
On 12 Dec 2011, at 15:20, Thomas Davie wrote:
> The way I read this is that while the thread making the call should block,
> other threads attempting to access the lock while the condition is not met
> should not block.
Correct. The -wait call will atomically release the lock and sleep. It will
return when the condition has been signalled.
> Here's GNUstep's implementation:
>> - (void) lockWhenCondition: (NSInteger)value
>> {
>> [_condition lock];
>> while (value != _condition_value)
>> {
>> [_condition wait];
>> }
>> }
>
> I'm pretty sure this doesn't match the right semantics if:
>
> The lock is initialised with a condition that isn't 5
> Thread 1 calls [lock lockWhenCondition:5];
Acquires the lock, checks the condition. The condition is false. Atomically
releases the lock and sleeps.
> Thread 2 calls [lock lock];
Acquires the lock.
> Thread 2 calls [lock unlockWithCondition:5];
Signals the condition variable. The -wait call is then blocked attempting to
acquire the lock. Releases the lock. The -wait call returns (with the lock).
Thread 1 proceeds.
> My expectation here would be for thread 1 to block at it's call to
> lockWhenCondition:, then for thread 2 to acquire the lock, then for it to
> give up the lock, and for thread 1 to unblock.
Yes, that's correct.
> The actual results with GNUstep's implementation are for thread 1 to not get
> the lock, but for it to become locked, then for thread 2 to block because
> thread 1 has the lock, and for the program to deadlock.
Do you have a complete test case that demonstrates this? I'm pretty sure that
the -base test suite has a test that looks like this and it passes...
> Wouldn't an implementation more like this be appropriate (note though that
> this too is buggy as it violate's NSCondition's API contract that wait must
> only be called while locked)?
That is a VERY important constraint! Violating is means calling a pthread API
with undefined behaviour! The -wait call atomically releases and reacquires
the lock after a signal - that is the entire point of it. Calling it without
the lock being held is nonsense.
>
>> - (void) lockWhenCondition: (NSInteger)value
> {
> while (1)
> {
> [_condition lock];
Now we hold the lock.
> if (value != _condition_value)
> {
> return;
> }
Now we're returning, while holding the lock, even though the condition doesn't
hold?
> [_condition unlock];
Now we're releasing the lock. If the condition is now signalled then we lose
the signal and the next line blocks forever.
> [_condition wait];
Now we block, atomically releasing the lock (that we don't hold, so entering
some undefined behaviour) and waiting for the signal that we just missed.
David
-- Sent from my brain
- NSConditionLock, Thomas Davie, 2011/12/12
- Re: NSConditionLock,
David Chisnall <=